Commit c13bd307 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parent 07f26527
...@@ -25,14 +25,17 @@ ...@@ -25,14 +25,17 @@
package weak package weak
import ( import (
"fmt"
"runtime" "runtime"
"sync" "sync"
"time"
"unsafe" "unsafe"
) )
// iface is how Go runtime represents an interface. // iface is how Go runtime represents an interface.
// //
// NOTE layout must be synchronized to Go runtime representation. // NOTE layout must be synchronized to Go runtime representation.
// NOTE depends on non-moving property of Go GC.
type iface struct { type iface struct {
typ uintptr // type typ uintptr // type
data uintptr // data data uintptr // data
...@@ -77,6 +80,11 @@ func NewRef(obj interface{}) *Ref { ...@@ -77,6 +80,11 @@ func NewRef(obj interface{}) *Ref {
var release func(interface{}) var release func(interface{})
release = func(obj interface{}) { release = func(obj interface{}) {
ifobj := *(*iface)(unsafe.Pointer(&obj))
if w.iface != ifobj {
panic(fmt.Sprintf("weak: release: w.iface != obj; w.iface=%x obj=%x", w.iface, ifobj))
}
// GC decided that the object is no longer reachable and // GC decided that the object is no longer reachable and
// scheduled us to run as finalizer. During the time till we // scheduled us to run as finalizer. During the time till we
// actually run, Ref.Get might have been come to run and // actually run, Ref.Get might have been come to run and
...@@ -102,15 +110,21 @@ func NewRef(obj interface{}) *Ref { ...@@ -102,15 +110,21 @@ func NewRef(obj interface{}) *Ref {
// If original object is still alive - it is returned. // If original object is still alive - it is returned.
// If not - nil is returned. // If not - nil is returned.
func (w *Ref) Get() (obj interface{}) { func (w *Ref) Get() (obj interface{}) {
get := false
w.mu.Lock() w.mu.Lock()
if w.state != objReleased { if w.state != objReleased {
w.state = objGot w.state = objGot
get = true
}
w.mu.Unlock()
if get {
time.Sleep(100*time.Nanosecond)
// recreate interface{} from saved words. // recreate interface{} from saved words.
// XXX do writes as pointers so that compiler emits write barriers to notify GC? // XXX do writes as pointers so that compiler emits write barriers to notify GC?
i := (*iface)(unsafe.Pointer(&obj)) i := (*iface)(unsafe.Pointer(&obj))
*i = w.iface *i = w.iface
} }
w.mu.Unlock()
return obj return obj
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment