diff --git a/.travis.yml b/.travis.yml index 7df76b9..f8e0d65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,6 +16,5 @@ matrix: - go: tip install: - - go get go4.org/syncutil - go get github.com/onsi/ginkgo - go get github.com/onsi/gomega diff --git a/cluster.go b/cluster.go index 62dfe4a..f758b01 100644 --- a/cluster.go +++ b/cluster.go @@ -8,8 +8,6 @@ import ( "sync/atomic" "time" - "go4.org/syncutil" - "github.com/go-redis/redis/internal" "github.com/go-redis/redis/internal/hashtag" "github.com/go-redis/redis/internal/pool" @@ -347,7 +345,7 @@ type ClusterClient struct { nodes *clusterNodes _state atomic.Value - cmdsInfoOnce syncutil.Once + cmdsInfoOnce internal.Once cmdsInfo map[string]*CommandInfo // Reports where slots reloading is in progress. diff --git a/internal/once.go b/internal/once.go new file mode 100644 index 0000000..64f4627 --- /dev/null +++ b/internal/once.go @@ -0,0 +1,60 @@ +/* +Copyright 2014 The Camlistore Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internal + +import ( + "sync" + "sync/atomic" +) + +// A Once will perform a successful action exactly once. +// +// Unlike a sync.Once, this Once's func returns an error +// and is re-armed on failure. +type Once struct { + m sync.Mutex + done uint32 +} + +// Do calls the function f if and only if Do has not been invoked +// without error for this instance of Once. In other words, given +// var once Once +// if once.Do(f) is called multiple times, only the first call will +// invoke f, even if f has a different value in each invocation unless +// f returns an error. A new instance of Once is required for each +// function to execute. +// +// Do is intended for initialization that must be run exactly once. Since f +// is niladic, it may be necessary to use a function literal to capture the +// arguments to a function to be invoked by Do: +// err := config.once.Do(func() error { return config.init(filename) }) +func (o *Once) Do(f func() error) error { + if atomic.LoadUint32(&o.done) == 1 { + return nil + } + // Slow-path. + o.m.Lock() + defer o.m.Unlock() + var err error + if o.done == 0 { + err = f() + if err == nil { + atomic.StoreUint32(&o.done, 1) + } + } + return err +} diff --git a/ring.go b/ring.go index 5d94519..be92510 100644 --- a/ring.go +++ b/ring.go @@ -9,8 +9,6 @@ import ( "sync/atomic" "time" - "go4.org/syncutil" - "github.com/go-redis/redis/internal" "github.com/go-redis/redis/internal/consistenthash" "github.com/go-redis/redis/internal/hashtag" @@ -136,7 +134,7 @@ type Ring struct { hash *consistenthash.Map shards map[string]*ringShard - cmdsInfoOnce syncutil.Once + cmdsInfoOnce internal.Once cmdsInfo map[string]*CommandInfo closed bool