diff options
Diffstat (limited to 'src/pkg/sync')
-rw-r--r-- | src/pkg/sync/Makefile | 3 | ||||
-rw-r--r-- | src/pkg/sync/asm_arm5.s | 2 | ||||
-rw-r--r-- | src/pkg/sync/mutex.go | 7 | ||||
-rw-r--r-- | src/pkg/sync/once.go | 35 | ||||
-rw-r--r-- | src/pkg/sync/once_test.go | 37 | ||||
-rw-r--r-- | src/pkg/sync/rwmutex.go | 2 |
6 files changed, 80 insertions, 6 deletions
diff --git a/src/pkg/sync/Makefile b/src/pkg/sync/Makefile index 4b9a05816..f843795b0 100644 --- a/src/pkg/sync/Makefile +++ b/src/pkg/sync/Makefile @@ -2,11 +2,12 @@ # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include ../../Make.$(GOARCH) +include ../../Make.inc TARG=sync GOFILES=\ mutex.go\ + once.go \ rwmutex.go\ # 386-specific object files diff --git a/src/pkg/sync/asm_arm5.s b/src/pkg/sync/asm_arm5.s index 3cdca0b87..2cb496887 100644 --- a/src/pkg/sync/asm_arm5.s +++ b/src/pkg/sync/asm_arm5.s @@ -16,7 +16,7 @@ TEXT ·cas(SB),7,$0 MOVW 4(FP), R1 // old MOVW 8(FP), R2 // new MOVW $1, R3 - MOVW $cas_mutex(SB), R4 + MOVW $runtime·cas_mutex(SB), R4 l: SWPW (R4), R3 // acquire mutex CMP $0, R3 diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go index b170370bc..9a2bb2bb4 100644 --- a/src/pkg/sync/mutex.go +++ b/src/pkg/sync/mutex.go @@ -3,9 +3,10 @@ // license that can be found in the LICENSE file. // The sync package provides basic synchronization primitives -// such as mutual exclusion locks. These are intended for use -// by low-level library routines. Higher-level synchronization -// is better done via channels and communication. +// such as mutual exclusion locks. Other than the Once type, +// most are intended for use by low-level library routines. +// Higher-level synchronization is better done via channels +// and communication. package sync import "runtime" diff --git a/src/pkg/sync/once.go b/src/pkg/sync/once.go new file mode 100644 index 000000000..8c877cdec --- /dev/null +++ b/src/pkg/sync/once.go @@ -0,0 +1,35 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sync + +// Once is an object that will perform exactly one action. +type Once struct { + m Mutex + done bool +} + +// Do calls the function f if and only if the method is being called for the +// first time with this receiver. In other words, given +// var once Once +// if Do(f) is called multiple times, only the first call will invoke f, +// even if f has a different value in each invocation. 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: +// config.once.Do(func() { config.init(filename) }) +// +// Because no call to Do returns until the one call to f returns, if f causes +// Do to be called, it will deadlock. +// +func (o *Once) Do(f func()) { + o.m.Lock() + defer o.m.Unlock() + if !o.done { + o.done = true + f() + } +} diff --git a/src/pkg/sync/once_test.go b/src/pkg/sync/once_test.go new file mode 100644 index 000000000..155954a49 --- /dev/null +++ b/src/pkg/sync/once_test.go @@ -0,0 +1,37 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sync_test + +import ( + . "sync" + "testing" +) + +type one int + +func (o *one) Increment() { + *o++ +} + +func run(once *Once, o *one, c chan bool) { + once.Do(func() { o.Increment() }) + c <- true +} + +func TestOnce(t *testing.T) { + o := new(one) + once := new(Once) + c := make(chan bool) + const N = 10 + for i := 0; i < N; i++ { + go run(once, o, c) + } + for i := 0; i < N; i++ { + <-c + } + if *o != 1 { + t.Errorf("once failed: %d is not 1", *o) + } +} diff --git a/src/pkg/sync/rwmutex.go b/src/pkg/sync/rwmutex.go index 0058cf252..06fd0b0ff 100644 --- a/src/pkg/sync/rwmutex.go +++ b/src/pkg/sync/rwmutex.go @@ -21,7 +21,7 @@ type RWMutex struct { // RLock locks rw for reading. // If the lock is already locked for writing or there is a writer already waiting -// to r the lock, RLock blocks until the writer has released the lock. +// to release the lock, RLock blocks until the writer has released the lock. func (rw *RWMutex) RLock() { // Use rw.r.Lock() to block granting the RLock if a goroutine // is waiting for its Lock. This is the prevent starvation of W in |