Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1148)

Delta Between Two Patch Sets: src/pkg/sync/pool.go

Issue 41860043: code review 41860043: sync: add Pool type (Closed)
Left Patch Set: diff -r c37a24ac952c https://go.googlecode.com/hg/ Created 10 years, 3 months ago
Right Patch Set: diff -r 477af6a8e51f https://go.googlecode.com/hg/ Created 10 years, 3 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/pkg/runtime/mgc0.c ('k') | src/pkg/sync/pool_test.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 // Copyright 2013 The Go Authors. All rights reserved. 1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style 2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file. 3 // license that can be found in the LICENSE file.
4 4
5 package sync 5 package sync
6 6
7 import "unsafe" 7 // A Pool is a set of temporary objects that may be individually saved
8 // and retrieved.
9 //
10 // Any item stored in the Pool may be removed automatically by the
11 // implementation at any time without notification.
12 // If the Pool holds the only reference when this happens, the item
13 // might be deallocated.
14 //
15 // A Pool is safe for use by multiple goroutines simultaneously.
16 //
17 // This is an experimental package and might not be released.
18 type Pool struct {
19 » next *Pool // for use by runtime. must be first.
20 » list []interface{} // offset known to runtime
21 » mu Mutex // guards list
8 22
9 // A Pool is a set of allocated objects to be reused. 23 » // New optionally specifies a function to generate
10 // It may be used by multiple goroutines simultaneously. 24 » // a value when Get would otherwise return nil.
11 // The Pool is drained during garbage collection. 25 » // It may not be changed concurrently with calls to Get.
12 type Pool struct {
13 » // New optionally specifies a function to return a new value
14 » // when Get would otherwise return nil.
15 New func() interface{} 26 New func() interface{}
16
17 mu Mutex // guards rest
18 cur uint32
19 gen uint32 // free is only valid if numgc == gen
20 free []poolItem
21 } 27 }
22 28
23 // A poolItem contains the two words of an interface{} value, xored to 29 func runtime_registerPool(*Pool)
24 // hide it from the garbage collector. It is only xor'd back to an
25 // interface{} if the pool's generation (numgc) matches.
26 //
27 // TODO(bradfitz): This is a temporary hacky mechanism until dvyukov
28 // re-implements the Pool in an efficient way.
29 type poolItem struct {
30 » i1, i2 uintptr
31 }
32
33 func newPoolItem(x interface{}) (pi poolItem) {
34 » pi = *((*poolItem)(unsafe.Pointer(&x)))
35 » pi.i1 = ^pi.i1
36 » pi.i2 = ^pi.i2
37 » return
38 }
39
40 func (pi *poolItem) Interface() (x interface{}) {
41 » return *(*interface{})(unsafe.Pointer(&poolItem{^pi.i1, ^pi.i2}))
42 }
43
44 func readNumGC(*uint32) // implemented in runtime/mgc0.c
45
46 var alwaysFalse = false
47 var globalI interface{}
48 30
49 // Put adds x to the pool. 31 // Put adds x to the pool.
50 func (p *Pool) Put(x interface{}) { 32 func (p *Pool) Put(x interface{}) {
51 » pi := newPoolItem(x) 33 » if x == nil {
52 34 » » return
35 » }
53 p.mu.Lock() 36 p.mu.Lock()
54 » readNumGC(&p.cur) 37 » if p.list == nil {
55 » if p.cur != p.gen { 38 » » runtime_registerPool(p)
56 » » p.gen = p.cur
57 » » p.free = p.free[:0]
58 } 39 }
59 » p.free = append(p.free, pi) 40 » p.list = append(p.list, x)
60 p.mu.Unlock() 41 p.mu.Unlock()
61
62 // Force x to stay live throughout,
63 // but don't actually race on globalI.
64 if alwaysFalse {
65 globalI = x
66 }
67 } 42 }
68 43
69 // Get removes and returns a value from the pool. 44 // Get selects an arbitrary item from the Pool, removes it from the
70 // If the pool is empty, Get returns nil, or the return 45 // Pool, and returns it to the caller.
71 // value of calling p.New. 46 // Get may choose to ignore the pool and treat it as empty.
47 // Callers should not assume any relation between values passed to Put and
48 // the values returned by Get.
49 //
50 // If Get would otherwise return nil and p.New is non-nil, Get returns
51 // the result of calling p.New.
72 func (p *Pool) Get() interface{} { 52 func (p *Pool) Get() interface{} {
53 p.mu.Lock()
73 var x interface{} 54 var x interface{}
74 55 » if n := len(p.list); n > 0 {
75 » p.mu.Lock() 56 » » x = p.list[n-1]
76 57 » » p.list[n-1] = nil // Just to be safe
77 » if len(p.free) > 0 { 58 » » p.list = p.list[:n-1]
78 » » last := p.free[len(p.free)-1]
79 » » p.free = p.free[:len(p.free)-1]
80 » » x = last.Interface()
81
82 » » // Now that we have x, double-check that no GC has occured
83 » » // even in the past few lines.
84 » » readNumGC(&p.cur)
85 » » if p.gen != p.cur {
86 » » » x = nil
87 » » » p.gen = p.cur
88 » » » p.free = p.free[:0]
89 » » }
90 } 59 }
91 p.mu.Unlock() 60 p.mu.Unlock()
92
93 if x == nil && p.New != nil { 61 if x == nil && p.New != nil {
94 x = p.New() 62 x = p.New()
95 } 63 }
96 return x 64 return x
97 } 65 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b