github.com/cocotyty/oneshot@v0.0.0-20210707064948-4d5a81d0b747/shot.go (about) 1 package oneshot 2 3 import ( 4 "sync/atomic" 5 "unsafe" 6 _ "unsafe" 7 ) 8 9 type Shot struct { 10 gp uintptr 11 } 12 13 func getG() uintptr 14 15 //go:linkname gopark runtime.gopark 16 func gopark(unlockf func(uintptr, unsafe.Pointer) bool, lock unsafe.Pointer, reason byte, traceEv byte, traceskip int) 17 18 //go:linkname goready runtime.goready 19 func goready(gp uintptr, traceskip int) 20 21 func commit(ug uintptr, xp unsafe.Pointer) bool { 22 x := (*Shot)(xp) 23 return atomic.CompareAndSwapUintptr(&x.gp, 0, ug) 24 } 25 26 func (x *Shot) Wait() { 27 gopark(commit, unsafe.Pointer(x), 1, 0, 0) 28 } 29 30 func (x *Shot) WakeUp() { 31 ugn := atomic.LoadUintptr(&x.gp) 32 if ugn != 0 { 33 goready(ugn, 0) 34 } else { 35 if !atomic.CompareAndSwapUintptr(&x.gp, 0, 1) { 36 ugn := atomic.LoadUintptr(&x.gp) 37 goready(ugn, 0) 38 } 39 } 40 }