-
Notifications
You must be signed in to change notification settings - Fork 0
/
use_pool.go
145 lines (118 loc) · 3.18 KB
/
use_pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package syncs
import (
"sync"
"github.com/devlights/gomy/output"
)
type _PooledObject struct {
v int
}
func newPooledObject(v int) *_PooledObject {
output.Stderrl("[New]", "Call newPooledObject()")
return &_PooledObject{v: v}
}
func (me *_PooledObject) Reset() {
me.v = 0
}
func (me *_PooledObject) Set(v int) {
me.v = v + 100
}
func (me *_PooledObject) Value() int {
return me.v
}
// UsePool は、sync.Poolのサンプルです。
//
// # REFERENCES
// - https://pkg.go.dev/sync@go1.21.4#Pool
func UsePool() error {
//
// sync.Pool を利用する際の注意点 (go doc より引用)
//
// > Any item stored in the Pool may be removed automatically at any time without notification.
// > If the Pool holds the only reference when this happens, the item might be deallocated.
//
// プールに保持されているオブジェクトは通知無しに自動削除される可能性がある。
// その際に、プールがそのオブジェクトを参照する唯一であれば、メモリから
// 開放される可能性がある。
//
// > A Pool must not be copied after first use.
//
// プールは、最初に使用した後はコピーしてはならない。
//
// > The Pool's New function should generally only return pointer types,
// > since a pointer can be put into the return interface value without an allocation
//
// ポインタは割り当てなしで戻りインターフェイス値に入れることができるため、
// プールの New 関数は通常、ポインタ型のみを返す必要がある.
//
const (
NumItems = 20
)
var (
pool = sync.Pool{
New: func() any {
return newPooledObject(0)
},
}
ch = make(chan int)
done = make(chan struct{})
wg = sync.WaitGroup{}
)
wg.Add(NumItems)
for i := 0; i < NumItems; i++ {
go func(i int, ch chan<- int) {
defer wg.Done()
// プールから取得
o := pool.Get().(*_PooledObject)
o.Reset()
o.Set(i)
v := o.Value()
// 使い終わったらプールに戻す
pool.Put(o)
ch <- v
}(i, ch)
}
go func() {
defer close(ch)
wg.Wait()
}()
go func(done chan<- struct{}, ch <-chan int) {
defer close(done)
for v := range ch {
output.Stderrl("[output]", v)
}
}(done, ch)
<-done
return nil
/*
$ task
task: Task "build" is up to date
task: [run] ./try-golang -onetime
ENTER EXAMPLE NAME: syncs_use_pool
[Name] "syncs_use_pool"
[New] Call newPooledObject()
[output] 113
[output] 114
[New] Call newPooledObject()
[output] 115
[New] Call newPooledObject()
[output] 116
[output] 117
[output] 118
[output] 119
[output] 103
[output] 100
[output] 101
[output] 108
[output] 106
[output] 107
[output] 104
[output] 109
[output] 110
[output] 112
[output] 105
[output] 111
[New] Call newPooledObject()
[output] 102
[Elapsed] 489.3µs
*/
}