Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(221)

Side by Side Diff: common/sync/mutexpool/pool.go

Issue 2640323003: common/sync/mutexpool: Add mutexpool. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | common/sync/mutexpool/pool_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 // Package mutexpool implements P, a pool of keyed mutexes. These mutexes are
6 // created on-demand and deleted when no longer referenced, so the pool's
7 // maximum size is a function of the maximum number of concurrent mutexes
8 // held at any given time.
9 //
10 // Package mutexpool is useful when coordinating access to resources that are
11 // not managed by the accessor such as remote resource accesses.
12 package mutexpool
13
14 import (
15 "sync"
16 )
17
18 // P is a pool of keyed mutexes. The zero value is a valid empty pool.
19 //
20 // A user can grab an arbitrary Mutex's lock by calling WithMutex with a key.
21 // If something else currently holds that Mutex's lock, WithMutex will block
22 // until it can claim the lock. When a key is no longer in use, it will be
23 // removed from P.
24 type P struct {
25 lock sync.Mutex
iannucci 2017/01/19 22:52:54 s/lock/mapLock ?
dnj 2017/01/19 22:59:19 Went with mutexesLock
26 mutexes map[interface{}]*mutexEntry
27 }
28
29 func (pc *P) getConfigLock(key interface{}) *mutexEntry {
30 // Does the lock already exist?
31 pc.lock.Lock()
32 defer pc.lock.Unlock()
33
34 if me := pc.mutexes[key]; me != nil {
35 me.count++
iannucci 2017/01/19 22:52:54 panic on overflow? uint64?
dnj 2017/01/19 22:59:19 Did both.
36 return me
37 }
38
39 if pc.mutexes == nil {
40 pc.mutexes = make(map[interface{}]*mutexEntry)
41 }
42 me := &mutexEntry{
43 count: 1, // Start with one ref.
44 }
45 pc.mutexes[key] = me
46 return me
47 }
48
49 func (pc *P) decRef(me *mutexEntry, key interface{}) {
50 pc.lock.Lock()
51 defer pc.lock.Unlock()
52
53 me.count--
54 if me.count <= 0 {
55 delete(pc.mutexes, key)
56 }
57 }
58
59 // WithMutex locks the Mutex matching the specified key and executes fn while
60 // holding its lock.
61 //
62 // If a mutex for key doesn't exist, one will be created, and will be
63 // automatically cleaned up when no longer referenced.
64 func (pc *P) WithMutex(key interface{}, fn func()) {
65 // Get a lock for this config key, and increment its reference.
66 me := pc.getConfigLock(key)
67 defer pc.decRef(me, key)
68
69 // Hold this lock's mutex and call "fn".
70 me.Lock()
71 defer me.Unlock()
72
73 fn()
74 }
75
76 type mutexEntry struct {
77 sync.Mutex
78
79 // count is the number of references to this mutexEntry. It is protected
80 // by P's lock.
81 count int
82 }
OLDNEW
« no previous file with comments | « no previous file | common/sync/mutexpool/pool_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698