Golang的copyCheck.check如何检测对象复制?
// copyChecker holds back pointer to itself to detect object copying.
type copyChecker uintptr
func (c *copyChecker) check() {
if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
!atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
uintptr(*c) != uintptr(unsafe.Pointer(c)) {
panic("sync.Cond is copied")
}
}
答案 0 :(得分:1)
创建它时,它将其值设置为自己的地址。要检查它是否已被复制,它会将其地址与存储的值进行比较。如果它被复制了,它的地址会有所不同,但是它的值会相同,所以不再指向它自己。
答案 1 :(得分:1)
好吧,所以,首先看一下copyChecker
是什么:它是uintptr
。因此,有一个关键点:声称不能在第一次使用后复制 。每次“使用”(导出的方法)都始于对对象的checker
进行检查。首次调用Cond
类型的方法之一时,它将存储其checker
的地址。任何将来的使用都会检查checker对象是否在存储的地址处。如果您将其复制,则副本必须具有不同的地址,这会引起恐慌。
实际检查的工作方式:
第一次遇到此问题时,c
为零,因此它与地址c
实际所在的地址不同。有一个原子交换,当且仅当当前值为零时,它才交换c
的地址,并确保原子交换。如果c
为零,或者c
的值不是其自己的地址,则可以进行第一个比较。比较可确保它不为零。因此,当进行第三次比较时,该值为零,并且此后已将其设置为当前地址(并且它们不会不相等),或者该值最初不是零。如果该值不为零,并且与当前地址也不相同,则意味着此Cond
是通过获取已经使用过的Cond
并将其复制到新地址中而制成的地址。