Golang的copyCheck.check如何检测对象复制?

时间:2018-02-01 03:07:21

标签: go

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")
    }
}

2 个答案:

答案 0 :(得分:1)

创建它时,它将其值设置为自己的地址。要检查它是否已被复制,它会将其地址与存储的值进行比较。如果它被复制了,它的地址会有所不同,但是它的值会相同,所以不再指向它自己。

答案 1 :(得分:1)

好吧,所以,首先看一下copyChecker是什么:它是uintptr。因此,有一个关键点:声称不能在第一次使用后复制 。每次“使用”(导出的方法)都始于对对象的checker进行检查。首次调用Cond类型的方法之一时,它将存储其checker的地址。任何将来的使用都会检查checker对象是否在存储的地址处。如果您将其复制,则副本必须具有不同的地址,这会引起恐慌。

实际检查的工作方式:

第一次遇到此问题时,c为零,因此它与地址c实际所在的地址不同。有一个原子交换,当且仅当当前值为零时,它才交换c的地址,并确保原子交换。如果c为零,或者c的值不是其自己的地址,则可以进行第一个比较。比较可确保它不为零。因此,当进行第三次比较时,该值为零,并且此后已将其设置为当前地址(并且它们不会不相等),或者该值最初不是零。如果该值不为零,并且与当前地址也不相同,则意味着此Cond是通过获取已经使用过的Cond并将其复制到新地址中而制成的地址。