@@ -11,7 +11,7 @@ type Pool interface {
1111 // Delegate job to a workers
1212 // will block if channel is full, you might want to wrap it with goroutine to avoid it
1313 // will panic if called after Stop()
14- Delegate (args ... interface {})
14+ Delegate (args ... interface {}) error
1515
1616 // AddWorker adds worker to the pool
1717 AddWorker (fn interface {}) error
@@ -20,42 +20,59 @@ type Pool interface {
2020
2121 // WorkersNum returns number of workers in the pool
2222 WorkersNum () int
23- // Stop all workers
23+
24+ // Stop removes all workers workers
25+ // to resume work add them again
2426 Stop ()
2527}
2628
29+ type quitCh chan interface {}
30+ type workers map [reflect.Value ][]quitCh
31+
2732type pool struct {
28- queue chan []reflect.Value
29- isQueueClosed bool
30- workers []reflect.Value
31- mtx sync.RWMutex
33+ queue chan []reflect.Value
34+ workers workers
35+ mtx sync.RWMutex
3236}
3337
34- func (p * pool ) Delegate (args ... interface {}) {
38+ func (p * pool ) Delegate (args ... interface {}) error {
39+ if len (p .workers ) == 0 {
40+ return fmt .Errorf ("there is no workers in pool" )
41+ }
42+
3543 p .queue <- buildQueueValue (args )
44+
45+ return nil
3646}
3747
3848func (p * pool ) AddWorker (fn interface {}) error {
3949 if err := isValidHandler (fn ); err != nil {
4050 return err
4151 }
4252
43- if p .isQueueClosed {
44- return fmt .Errorf ("can not add new worker to already stopped pool" )
45- }
46-
4753 worker := reflect .ValueOf (fn )
4854
49- go func () {
50- for args := range p .queue {
51- worker .Call (args )
52- }
53- }()
54-
5555 p .mtx .Lock ()
5656 defer p .mtx .Unlock ()
5757
58- p .workers = append (p .workers , worker )
58+ q := make (quitCh )
59+
60+ if _ , ok := p .workers [worker ]; ! ok {
61+ p .workers [worker ] = []quitCh {q }
62+ } else {
63+ p .workers [worker ] = append (p .workers [worker ], q )
64+ }
65+
66+ go func () {
67+ for {
68+ select {
69+ case args := <- p .queue :
70+ worker .Call (args )
71+ case <- q :
72+ return
73+ }
74+ }
75+ }()
5976
6077 return nil
6178}
@@ -65,27 +82,37 @@ func (p *pool) RemoveWorker(fn interface{}) error {
6582 return err
6683 }
6784
68- rv := reflect .ValueOf (fn )
85+ worker := reflect .ValueOf (fn )
6986
7087 p .mtx .Lock ()
7188 defer p .mtx .Unlock ()
7289
73- for i , worker := range p .workers {
74- if worker == rv {
75- p .workers = append (p .workers [:i ], p .workers [i + 1 :]... )
76- }
90+ if len (p .workers [worker ]) > 0 {
91+ close (p .workers [worker ][len (p .workers [worker ])- 1 ])
92+
93+ p .workers [worker ] = p .workers [worker ][:len (p .workers [worker ])- 1 ]
94+ } else {
95+ delete (p .workers , worker )
7796 }
7897
7998 return nil
8099}
81100
82101func (p * pool ) WorkersNum () int {
83- return len (p .workers )
102+ sum := 0
103+ for _ , qChs := range p .workers {
104+ sum += len (qChs )
105+ }
106+
107+ return sum
84108}
85109
86110func (p * pool ) Stop () {
87- close (p .queue )
88- p .isQueueClosed = true
111+ for _ , qChs := range p .workers {
112+ for _ , ch := range qChs {
113+ close (ch )
114+ }
115+ }
89116}
90117
91118func isValidHandler (fn interface {}) error {
@@ -110,6 +137,6 @@ func buildQueueValue(args []interface{}) []reflect.Value {
110137func New (queueLength int ) Pool {
111138 return & pool {
112139 queue : make (chan []reflect.Value , queueLength ),
113- workers : make ([]reflect. Value , 0 ),
140+ workers : make (workers ),
114141 }
115142}
0 commit comments