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