mirror of https://github.com/golang/go.git
cmd/vet: check sync.* types' copying
Embed noLock struct into the following types, so `go vet -copylocks` catches their copying additionally to types containing sync.Mutex: - sync.Cond - sync.WaitGroup - sync.Pool - atomic.Value Fixes #14582 Change-Id: Icb543ef5ad10524ad239a15eec8a9b334b0e0660 Reviewed-on: https://go-review.googlesource.com/22015 Reviewed-by: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
258a4c3daf
commit
c81a3532fe
|
|
@ -1,6 +1,9 @@
|
|||
package testdata
|
||||
|
||||
import "sync"
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
)
|
||||
|
||||
func OkFunc() {
|
||||
var x *sync.Mutex
|
||||
|
|
@ -66,3 +69,72 @@ func BadFunc() {
|
|||
new := func(interface{}) {}
|
||||
new(t) // ERROR "function call copies lock value: testdata.Tlock contains sync.Once contains sync.Mutex"
|
||||
}
|
||||
|
||||
// SyncTypesCheck checks copying of sync.* types except sync.Mutex
|
||||
func SyncTypesCheck() {
|
||||
// sync.RWMutex copying
|
||||
var rwmuX sync.RWMutex
|
||||
var rwmuXX = sync.RWMutex{}
|
||||
rwmuX1 := new(sync.RWMutex)
|
||||
rwmuY := rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
|
||||
rwmuY = rwmuX // ERROR "assignment copies lock value to rwmuY: sync.RWMutex"
|
||||
var rwmuYY = rwmuX // ERROR "variable declaration copies lock value to rwmuYY: sync.RWMutex"
|
||||
rwmuP := &rwmuX
|
||||
rwmuZ := &sync.RWMutex{}
|
||||
|
||||
// sync.Cond copying
|
||||
var condX sync.Cond
|
||||
var condXX = sync.Cond{}
|
||||
condX1 := new(sync.Cond)
|
||||
condY := condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
|
||||
condY = condX // ERROR "assignment copies lock value to condY: sync.Cond contains sync.noCopy"
|
||||
var condYY = condX // ERROR "variable declaration copies lock value to condYY: sync.Cond contains sync.noCopy"
|
||||
condP := &condX
|
||||
condZ := &sync.Cond{
|
||||
L: &sync.Mutex{},
|
||||
}
|
||||
condZ = sync.NewCond(&sync.Mutex{})
|
||||
|
||||
// sync.WaitGroup copying
|
||||
var wgX sync.WaitGroup
|
||||
var wgXX = sync.WaitGroup{}
|
||||
wgX1 := new(sync.WaitGroup)
|
||||
wgY := wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
|
||||
wgY = wgX // ERROR "assignment copies lock value to wgY: sync.WaitGroup contains sync.noCopy"
|
||||
var wgYY = wgX // ERROR "variable declaration copies lock value to wgYY: sync.WaitGroup contains sync.noCopy"
|
||||
wgP := &wgX
|
||||
wgZ := &sync.WaitGroup{}
|
||||
|
||||
// sync.Pool copying
|
||||
var poolX sync.Pool
|
||||
var poolXX = sync.Pool{}
|
||||
poolX1 := new(sync.Pool)
|
||||
poolY := poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
|
||||
poolY = poolX // ERROR "assignment copies lock value to poolY: sync.Pool contains sync.noCopy"
|
||||
var poolYY = poolX // ERROR "variable declaration copies lock value to poolYY: sync.Pool contains sync.noCopy"
|
||||
poolP := &poolX
|
||||
poolZ := &sync.Pool{}
|
||||
|
||||
// sync.Once copying
|
||||
var onceX sync.Once
|
||||
var onceXX = sync.Once{}
|
||||
onceX1 := new(sync.Once)
|
||||
onceY := onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
|
||||
onceY = onceX // ERROR "assignment copies lock value to onceY: sync.Once contains sync.Mutex"
|
||||
var onceYY = onceX // ERROR "variable declaration copies lock value to onceYY: sync.Once contains sync.Mutex"
|
||||
onceP := &onceX
|
||||
onceZ := &sync.Once{}
|
||||
}
|
||||
|
||||
// AtomicTypesCheck checks copying of sync/atomic types
|
||||
func AtomicTypesCheck() {
|
||||
// atomic.Value copying
|
||||
var vX atomic.Value
|
||||
var vXX = atomic.Value{}
|
||||
vX1 := new(atomic.Value)
|
||||
vY := vX // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
|
||||
vY = vX // ERROR "assignment copies lock value to vY: sync/atomic.Value contains sync/atomic.noCopy"
|
||||
var vYY = vX // ERROR "variable declaration copies lock value to vYY: sync/atomic.Value contains sync/atomic.noCopy"
|
||||
vP := &vX
|
||||
vZ := &atomic.Value{}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,11 @@ import (
|
|||
// Values can be created as part of other data structures.
|
||||
// The zero value for a Value returns nil from Load.
|
||||
// Once Store has been called, a Value must not be copied.
|
||||
//
|
||||
// A Value must not be copied after first use.
|
||||
type Value struct {
|
||||
noCopy noCopy
|
||||
|
||||
v interface{}
|
||||
}
|
||||
|
||||
|
|
@ -83,3 +87,13 @@ func (v *Value) Store(x interface{}) {
|
|||
// Disable/enable preemption, implemented in runtime.
|
||||
func runtime_procPin()
|
||||
func runtime_procUnpin()
|
||||
|
||||
// noCopy may be embedded into structs which must not be copied
|
||||
// after the first use.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/8005#issuecomment-190753527
|
||||
// for details.
|
||||
type noCopy struct{}
|
||||
|
||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
||||
func (*noCopy) Lock() {}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ import (
|
|||
// A Cond can be created as part of other structures.
|
||||
// A Cond must not be copied after first use.
|
||||
type Cond struct {
|
||||
noCopy noCopy
|
||||
|
||||
// L is held while observing or changing the condition
|
||||
L Locker
|
||||
|
||||
|
|
@ -84,3 +86,13 @@ func (c *copyChecker) check() {
|
|||
panic("sync.Cond is copied")
|
||||
}
|
||||
}
|
||||
|
||||
// noCopy may be embedded into structs which must not be copied
|
||||
// after the first use.
|
||||
//
|
||||
// See https://github.com/golang/go/issues/8005#issuecomment-190753527
|
||||
// for details.
|
||||
type noCopy struct{}
|
||||
|
||||
// Lock is a no-op used by -copylocks checker from `go vet`.
|
||||
func (*noCopy) Lock() {}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import (
|
|||
// A Mutex is a mutual exclusion lock.
|
||||
// Mutexes can be created as part of other structures;
|
||||
// the zero value for a Mutex is an unlocked mutex.
|
||||
//
|
||||
// A Mutex must not be copied after first use.
|
||||
type Mutex struct {
|
||||
state int32
|
||||
sema uint32
|
||||
|
|
|
|||
|
|
@ -40,7 +40,10 @@ import (
|
|||
// that scenario. It is more efficient to have such objects implement their own
|
||||
// free list.
|
||||
//
|
||||
// A Pool must not be copied after first use.
|
||||
type Pool struct {
|
||||
noCopy noCopy
|
||||
|
||||
local unsafe.Pointer // local fixed-size per-P pool, actual type is [P]poolLocal
|
||||
localSize uintptr // size of the local array
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ import (
|
|||
// RWMutexes can be created as part of other
|
||||
// structures; the zero value for a RWMutex is
|
||||
// an unlocked mutex.
|
||||
//
|
||||
// An RWMutex must not be copied after first use.
|
||||
type RWMutex struct {
|
||||
w Mutex // held if there are pending writers
|
||||
writerSem uint32 // semaphore for writers to wait for completing readers
|
||||
|
|
|
|||
|
|
@ -15,7 +15,11 @@ import (
|
|||
// goroutines to wait for. Then each of the goroutines
|
||||
// runs and calls Done when finished. At the same time,
|
||||
// Wait can be used to block until all goroutines have finished.
|
||||
//
|
||||
// A WaitGroup must not be copied after first use.
|
||||
type WaitGroup struct {
|
||||
noCopy noCopy
|
||||
|
||||
// 64-bit value: high 32 bits are counter, low 32 bits are waiter count.
|
||||
// 64-bit atomic operations require 64-bit alignment, but 32-bit
|
||||
// compilers do not ensure it. So we allocate 12 bytes and then use
|
||||
|
|
|
|||
Loading…
Reference in New Issue