Skip to content

Commit e56e35d

Browse files
committed
初步增加协程池
1 parent 6ae72d6 commit e56e35d

4 files changed

Lines changed: 196 additions & 0 deletions

File tree

pool.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package goes
6+
7+
import (
8+
"sync"
9+
10+
"github.com/FishGoddess/goes/pkg/spinlock"
11+
)
12+
13+
type Pool struct {
14+
workers []*worker
15+
index int
16+
closed bool
17+
18+
wg sync.WaitGroup
19+
lock sync.Locker
20+
}
21+
22+
func NewPool(size int, workerLimit int) *Pool {
23+
if size <= 0 {
24+
panic("goes: pool size <= 0")
25+
}
26+
27+
pool := &Pool{
28+
workers: make([]*worker, 0, size),
29+
index: 0,
30+
closed: false,
31+
lock: spinlock.New(),
32+
}
33+
34+
for range size {
35+
worker := newWorker(pool, workerLimit)
36+
pool.workers = append(pool.workers, worker)
37+
}
38+
39+
return pool
40+
}
41+
42+
func (p *Pool) Go(f func()) {
43+
p.lock.Lock()
44+
defer p.lock.Unlock()
45+
46+
if p.closed {
47+
return
48+
}
49+
50+
worker := p.workers[p.index]
51+
worker.Accept(f)
52+
53+
p.index++
54+
55+
if p.index >= len(p.workers) {
56+
p.index = 0
57+
}
58+
}
59+
60+
func (p *Pool) Wait() {
61+
p.wg.Wait()
62+
}
63+
64+
func (p *Pool) Close() {
65+
p.lock.Lock()
66+
defer p.lock.Unlock()
67+
68+
for _, worker := range p.workers {
69+
worker.Done()
70+
}
71+
72+
p.wg.Wait()
73+
p.closed = true
74+
}

pool_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package goes
6+
7+
import (
8+
"sync"
9+
"testing"
10+
"time"
11+
)
12+
13+
// go test -v -cover -run=^TestPool$
14+
func TestPool(t *testing.T) {
15+
size := 16
16+
workerLimit := 1024
17+
pool := NewPool(size, workerLimit)
18+
19+
var countMap = make(map[int64]int, 16)
20+
var lock sync.Mutex
21+
22+
totalCount := 10 * size
23+
for i := 0; i < totalCount; i++ {
24+
pool.Go(func() {
25+
now := time.Now().UnixMilli() / 10
26+
27+
lock.Lock()
28+
countMap[now] = countMap[now] + 1
29+
lock.Unlock()
30+
31+
time.Sleep(10 * time.Millisecond)
32+
})
33+
}
34+
35+
pool.Close()
36+
pool.Wait()
37+
38+
gotTotalCount := 0
39+
for now, count := range countMap {
40+
gotTotalCount = gotTotalCount + count
41+
42+
if count != size {
43+
t.Fatalf("now %d: count %d != size %d", now, count, size)
44+
}
45+
}
46+
47+
if gotTotalCount != totalCount {
48+
t.Fatalf("gotTotalCount %d != totalCount %d", gotTotalCount, totalCount)
49+
}
50+
}

worker.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package goes
6+
7+
type worker struct {
8+
pool *Pool
9+
tasks chan func()
10+
}
11+
12+
func newWorker(pool *Pool, limit int) *worker {
13+
if limit <= 0 {
14+
panic("goes: worker limit <= 0")
15+
}
16+
17+
w := &worker{
18+
pool: pool,
19+
tasks: make(chan func(), limit),
20+
}
21+
22+
w.work()
23+
return w
24+
}
25+
26+
func (w *worker) handle(task func()) {
27+
if task == nil {
28+
return
29+
}
30+
31+
defer func() {
32+
if r := recover(); r != nil {
33+
panic(r) // TODO recover from panic
34+
}
35+
}()
36+
37+
task()
38+
}
39+
40+
func (w *worker) work() {
41+
w.pool.wg.Add(1)
42+
go func() {
43+
defer w.pool.wg.Done()
44+
45+
for task := range w.tasks {
46+
if task == nil {
47+
break
48+
}
49+
50+
w.handle(task)
51+
}
52+
53+
close(w.tasks)
54+
}()
55+
}
56+
57+
func (w *worker) Accept(task func()) {
58+
if task == nil {
59+
return
60+
}
61+
62+
w.tasks <- task
63+
}
64+
65+
func (w *worker) Done() {
66+
w.tasks <- nil
67+
}

worker_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package goes

0 commit comments

Comments
 (0)