github.com/MeteorsLiu/simpleMQ@v1.0.3/queue/simple.go (about)

     1  package queue
     2  
     3  import (
     4  	"sync"
     5  )
     6  
     7  const (
     8  	DefaultSqSize = 1024
     9  )
    10  
    11  type SimpleQueue struct {
    12  	closeRW   sync.RWMutex
    13  	isClosed  bool
    14  	taskQueue chan Task
    15  }
    16  
    17  func NewSimpleQueue(opts ...Options) Queue {
    18  	s := &SimpleQueue{}
    19  	for _, o := range opts {
    20  		o(s)
    21  	}
    22  	if cap(s.taskQueue) == 0 {
    23  		s.taskQueue = make(chan Task, DefaultSqSize)
    24  	}
    25  	return s
    26  }
    27  func (s *SimpleQueue) Resize(capSize int) bool {
    28  	// stop executing all the new tasks
    29  	s.closeRW.Lock()
    30  	defer s.closeRW.Unlock()
    31  	if s.isClosed {
    32  		return false
    33  	}
    34  	newTaskQueue := make(chan Task, capSize)
    35  	defer func() {
    36  		s.taskQueue = newTaskQueue
    37  	}()
    38  	// initialize or fast resize
    39  	if cap(s.taskQueue) == 0 || len(s.taskQueue) == 0 {
    40  		return true
    41  	}
    42  	// a hot resize
    43  	for {
    44  		select {
    45  		case task := <-s.taskQueue:
    46  			select {
    47  			case newTaskQueue <- task:
    48  			default:
    49  				return true
    50  			}
    51  		default:
    52  			return true
    53  		}
    54  	}
    55  }
    56  
    57  func (s *SimpleQueue) Cap() int {
    58  	return cap(s.taskQueue)
    59  }
    60  func (s *SimpleQueue) Len() int {
    61  	return len(s.taskQueue)
    62  }
    63  
    64  func (s *SimpleQueue) Free() int {
    65  	return cap(s.taskQueue) - len(s.taskQueue)
    66  }
    67  
    68  func (s *SimpleQueue) IsClosed() bool {
    69  	s.closeRW.RLock()
    70  	defer s.closeRW.RUnlock()
    71  	return s.isClosed
    72  }
    73  
    74  // close wait until all tasks are executed.
    75  func (s *SimpleQueue) Close() {
    76  	// wake up the subscribers
    77  	// don't lock first,
    78  	// close first to avoid deadlock when the queue is empty.
    79  	close(s.taskQueue)
    80  	s.closeRW.Lock()
    81  	s.isClosed = true
    82  	s.closeRW.Unlock()
    83  }
    84  
    85  func (s *SimpleQueue) Publish(t Task) bool {
    86  	s.closeRW.RLock()
    87  	defer s.closeRW.RUnlock()
    88  	if s.isClosed {
    89  		return false
    90  	}
    91  	select {
    92  	case s.taskQueue <- t:
    93  	default:
    94  		return false
    95  	}
    96  	return true
    97  }
    98  
    99  func (s *SimpleQueue) ForcePublish(t Task) error {
   100  	s.closeRW.RLock()
   101  	defer s.closeRW.RUnlock()
   102  	if s.isClosed {
   103  		return ErrQueueClosed
   104  	}
   105  	s.taskQueue <- t
   106  	return nil
   107  }
   108  func (s *SimpleQueue) Subscribe() (chan Task, error) {
   109  	s.closeRW.RLock()
   110  	defer s.closeRW.RUnlock()
   111  	if s.isClosed {
   112  		return nil, ErrQueueClosed
   113  	}
   114  	return s.taskQueue, nil
   115  }
   116  func (s *SimpleQueue) TryPop() (Task, bool) {
   117  	s.closeRW.RLock()
   118  	defer s.closeRW.RUnlock()
   119  	if s.isClosed {
   120  		return nil, false
   121  	}
   122  	select {
   123  	case t := <-s.taskQueue:
   124  		return t, true
   125  	default:
   126  	}
   127  	return nil, false
   128  }
   129  
   130  func (s *SimpleQueue) Pop() (Task, error) {
   131  	s.closeRW.RLock()
   132  	defer s.closeRW.RUnlock()
   133  	if s.isClosed {
   134  		return nil, ErrQueueClosed
   135  	}
   136  	task, ok := <-s.taskQueue
   137  	if !ok {
   138  		return nil, ErrQueueClosed
   139  	}
   140  	return task, nil
   141  }
   142  
   143  func (s *SimpleQueue) Copy() []Task {
   144  	s.closeRW.Lock()
   145  	defer s.closeRW.Unlock()
   146  	if s.isClosed {
   147  		return nil
   148  	}
   149  	var tasks []Task
   150  	for i := 0; i < len(s.taskQueue); i++ {
   151  		task := <-s.taskQueue
   152  		tasks = append(tasks, task)
   153  		// don't effect the queue, re-push
   154  		s.taskQueue <- task
   155  	}
   156  	return tasks
   157  }
   158  
   159  func (s *SimpleQueue) Save(f func(Task)) {
   160  	s.closeRW.Lock()
   161  	defer s.closeRW.Unlock()
   162  	if s.isClosed {
   163  		return
   164  	}
   165  	defer func() {
   166  		s.isClosed = true
   167  		// wake up the subscribers
   168  		close(s.taskQueue)
   169  	}()
   170  	for {
   171  		select {
   172  		case task := <-s.taskQueue:
   173  			f(task)
   174  		default:
   175  			return
   176  		}
   177  	}
   178  }