From 909ffd1998a5b4f5df8bbb34dc673c64246b7002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ken-H=C3=A5vard=20Lieng?= Date: Fri, 11 Dec 2015 17:06:29 +0100 Subject: [PATCH] Use resettable sync.Once instead of reassignment --- Godeps/Godeps.json | 6 ++- .../src/github.com/matryer/resync/.gitignore | 24 ++++++++++++ .../src/github.com/matryer/resync/README.md | 27 +++++++++++++ .../src/github.com/matryer/resync/once.go | 38 +++++++++++++++++++ .../github.com/matryer/resync/once_test.go | 35 +++++++++++++++++ irc/client.go | 4 +- irc/conn.go | 3 +- 7 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 Godeps/_workspace/src/github.com/matryer/resync/.gitignore create mode 100644 Godeps/_workspace/src/github.com/matryer/resync/README.md create mode 100644 Godeps/_workspace/src/github.com/matryer/resync/once.go create mode 100644 Godeps/_workspace/src/github.com/matryer/resync/once_test.go diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json index d0c00e61..0fa4a942 100644 --- a/Godeps/Godeps.json +++ b/Godeps/Godeps.json @@ -1,6 +1,6 @@ { "ImportPath": "github.com/khlieng/dispatch", - "GoVersion": "go1.4.2", + "GoVersion": "go1.5.2", "Packages": [ "./..." ], @@ -67,6 +67,10 @@ "Comment": "v1.5.2", "Rev": "d5929c67198951106f49f7ea425198d0f1a08f7f" }, + { + "ImportPath": "github.com/matryer/resync", + "Rev": "3d7f7ed881e1fcb5d89be33f3eb4717ed379e7b1" + }, { "ImportPath": "github.com/mitchellh/go-homedir", "Rev": "1f6da4a72e57d4e7edd4a7295a585e0a3999a2d4" diff --git a/Godeps/_workspace/src/github.com/matryer/resync/.gitignore b/Godeps/_workspace/src/github.com/matryer/resync/.gitignore new file mode 100644 index 00000000..daf913b1 --- /dev/null +++ b/Godeps/_workspace/src/github.com/matryer/resync/.gitignore @@ -0,0 +1,24 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof diff --git a/Godeps/_workspace/src/github.com/matryer/resync/README.md b/Godeps/_workspace/src/github.com/matryer/resync/README.md new file mode 100644 index 00000000..581b3ba9 --- /dev/null +++ b/Godeps/_workspace/src/github.com/matryer/resync/README.md @@ -0,0 +1,27 @@ +# resync + +`sync.Once` with `Reset()` + + * See [sync.Once](http://golang.org/pkg/sync/#Once) + +## Example + +The following example examines how `resync.Once` could be used in a HTTP server situation. + +``` +// use it just like sync.Once +var once resync.Once + +// handle a web request +func handleRequest(w http.ResponseWriter, r *http.Request) { + once.Do(func(){ + // load templates or something + }) + // TODO: respond +} + +// handle some request that indicates things have changed +func handleResetRequest(w http.ResponseWriter, r *http.Request) { + once.Reset() // call Reset to cause initialisation to happen again above +} +``` diff --git a/Godeps/_workspace/src/github.com/matryer/resync/once.go b/Godeps/_workspace/src/github.com/matryer/resync/once.go new file mode 100644 index 00000000..54c7bf2a --- /dev/null +++ b/Godeps/_workspace/src/github.com/matryer/resync/once.go @@ -0,0 +1,38 @@ +package resync + +import ( + "sync" + "sync/atomic" +) + +// Once is an object that will perform exactly one action +// until Reset is called. +// See http://golang.org/pkg/sync/#Once +type Once struct { + m sync.Mutex + done uint32 +} + +// Do simulates sync.Once.Do by executing the specified function +// only once, until Reset is called. +// See http://golang.org/pkg/sync/#Once +func (o *Once) Do(f func()) { + if atomic.LoadUint32(&o.done) == 1 { + return + } + // Slow-path. + o.m.Lock() + defer o.m.Unlock() + if o.done == 0 { + defer atomic.StoreUint32(&o.done, 1) + f() + } +} + +// Reset indicates that the next call to Do should actually be called +// once again. +func (o *Once) Reset() { + o.m.Lock() + defer o.m.Unlock() + atomic.StoreUint32(&o.done, 0) +} diff --git a/Godeps/_workspace/src/github.com/matryer/resync/once_test.go b/Godeps/_workspace/src/github.com/matryer/resync/once_test.go new file mode 100644 index 00000000..fe0df9bc --- /dev/null +++ b/Godeps/_workspace/src/github.com/matryer/resync/once_test.go @@ -0,0 +1,35 @@ +package resync_test + +import ( + "testing" + + "github.com/cheekybits/is" + "github.com/khlieng/dispatch/Godeps/_workspace/src/github.com/matryer/resync" +) + +func TestOnceReset(t *testing.T) { + is := is.New(t) + var calls int + var c resync.Once + c.Do(func() { + calls++ + }) + c.Do(func() { + calls++ + }) + c.Do(func() { + calls++ + }) + is.Equal(calls, 1) + c.Reset() + c.Do(func() { + calls++ + }) + c.Do(func() { + calls++ + }) + c.Do(func() { + calls++ + }) + is.Equal(calls, 2) +} diff --git a/irc/client.go b/irc/client.go index bf95a425..7d9cecef 100644 --- a/irc/client.go +++ b/irc/client.go @@ -6,6 +6,8 @@ import ( "net" "strings" "sync" + + "github.com/khlieng/dispatch/Godeps/_workspace/src/github.com/matryer/resync" ) type Client struct { @@ -29,7 +31,7 @@ type Client struct { quit chan struct{} reconnect chan struct{} ready sync.WaitGroup - once sync.Once + once resync.Once lock sync.Mutex } diff --git a/irc/conn.go b/irc/conn.go index 24698146..e0a6c034 100644 --- a/irc/conn.go +++ b/irc/conn.go @@ -6,7 +6,6 @@ import ( "fmt" "net" "strings" - "sync" "time" ) @@ -107,7 +106,7 @@ func (c *Client) run() { case <-c.reconnect: c.reconnect = make(chan struct{}) - c.once = sync.Once{} + c.once.Reset() c.tryConnect() } }