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 }