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

Unified Diff: go/src/infra/gae/libs/memlock/memlock.go

Issue 1233413002: Simplify memlock and make it less racy. (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git@master
Patch Set: Created 5 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | go/src/infra/gae/libs/memlock/memlock_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: go/src/infra/gae/libs/memlock/memlock.go
diff --git a/go/src/infra/gae/libs/memlock/memlock.go b/go/src/infra/gae/libs/memlock/memlock.go
index fee7dcd2374ddd9690f0325b29c06f8321001e77..c3004c625ecb10d80181e364f337e037842a5700 100644
--- a/go/src/infra/gae/libs/memlock/memlock.go
+++ b/go/src/infra/gae/libs/memlock/memlock.go
@@ -12,7 +12,6 @@ import (
"bytes"
"errors"
"golang.org/x/net/context"
- "sync/atomic"
"time"
"infra/gae/libs/gae"
@@ -58,7 +57,7 @@ var memcacheLockTime = 16 * time.Second
// the same data must use the same key. clientID is the unique identifier for
// this client (lock-holder). If it's empty then TryWithLock() will return
// ErrEmptyClientID.
dnj 2015/07/17 18:01:35 Document that the context that "f" is called with
iannucci 2015/07/17 18:08:25 I think you're misunderstanding how the cancelatio
dnj 2015/07/17 18:10:29 Ah bad comment on my part, I was mostly suggesting
-func TryWithLock(ctx context.Context, key, clientID string, f func(check func() bool) error) error {
+func TryWithLock(ctx context.Context, key, clientID string, f func(context.Context) error) error {
if len(clientID) == 0 {
return ErrEmptyClientID
}
@@ -128,39 +127,36 @@ func TryWithLock(ctx context.Context, key, clientID string, f func(check func()
}
// At this point we nominally have the lock (at least for memcacheLockTime).
-
- stopChan := make(chan struct{})
- stoppedChan := make(chan struct{})
- held := uint32(1)
-
+ finished := make(chan struct{})
+ subCtx, cancelFunc := context.WithCancel(ctx)
dnj 2015/07/17 18:01:35 Main concern using contexts here is that if the pa
iannucci 2015/07/17 18:08:25 Yes
defer func() {
- close(stopChan)
- <-stoppedChan // this blocks TryWithLock until the goroutine below quits.
+ cancelFunc()
+ <-finished
}()
// This goroutine checks to see if we still posess the lock, and refreshes it
- // if we do. It will stop doing this when either stopChan is activated (e.g.
- // the user's function returns) or we lose the lock (memcache flake, etc.).
+ // if we do.
go func() {
- defer close(stoppedChan)
+ defer func() {
+ cancelFunc()
+ close(finished)
+ }()
checkLoop:
for {
select {
- case <-stopChan:
+ case <-subCtx.Done():
break checkLoop
case <-clock.Get(ctx).After(delay):
}
if !checkAnd(refresh) {
- atomic.StoreUint32(&held, 0)
log.Warningf("lost lock: %s", err)
return
}
}
checkAnd(release)
- atomic.StoreUint32(&held, 0)
}()
- return f(func() bool { return atomic.LoadUint32(&held) == 1 })
+ return f(subCtx)
}
« no previous file with comments | « no previous file | go/src/infra/gae/libs/memlock/memlock_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698