Index: item.go |
diff --git a/item.go b/item.go |
index 4159b76fdec253987f6fc1b626761ce7367ff634..7fa580523ba50c0b6972dc17b7c23c075fe93f33 100644 |
--- a/item.go |
+++ b/item.go |
@@ -4,21 +4,23 @@ import ( |
"encoding/binary" |
"errors" |
"fmt" |
+ "sync" |
"sync/atomic" |
- "unsafe" |
) |
// A persistable item. |
type Item struct { |
- Transient unsafe.Pointer // For any ephemeral data; atomic CAS recommended. |
- Key, Val []byte // Val may be nil if not fetched into memory yet. |
- Priority int32 // Use rand.Int31() for probabilistic balancing. |
+ Transient interface{} // For any ephemeral data. |
+ Key, Val []byte // Val may be nil if not fetched into memory yet. |
+ Priority int32 // Use rand.Int31() for probabilistic balancing. |
} |
// A persistable item and its persistence location. |
type itemLoc struct { |
- loc unsafe.Pointer // *ploc - can be nil if item is dirty (not yet persisted). |
- item unsafe.Pointer // *Item - can be nil if item is not fetched into memory yet. |
+ m sync.Mutex |
+ |
+ loc *ploc // can be nil if item is dirty (not yet persisted). |
+ item *Item // can be nil if item is not fetched into memory yet. |
} |
var empty_itemLoc = &itemLoc{} |
@@ -47,11 +49,31 @@ func (i *Item) Copy() *Item { |
} |
func (i *itemLoc) Loc() *ploc { |
- return (*ploc)(atomic.LoadPointer(&i.loc)) |
+ i.m.Lock() |
+ defer i.m.Unlock() |
+ return i.loc |
+} |
+ |
+func (i *itemLoc) setLoc(n *ploc) { |
+ i.m.Lock() |
+ defer i.m.Unlock() |
+ i.loc = n |
} |
func (i *itemLoc) Item() *Item { |
- return (*Item)(atomic.LoadPointer(&i.item)) |
+ i.m.Lock() |
+ defer i.m.Unlock() |
+ return i.item |
+} |
+ |
+func (i *itemLoc) casItem(o, n *Item) bool { |
+ i.m.Lock() |
+ defer i.m.Unlock() |
+ if i.item == o { |
+ i.item = n |
+ return true |
+ } |
+ return false |
} |
func (i *itemLoc) Copy(src *itemLoc) { |
@@ -59,8 +81,13 @@ func (i *itemLoc) Copy(src *itemLoc) { |
i.Copy(empty_itemLoc) |
return |
} |
- atomic.StorePointer(&i.loc, unsafe.Pointer(src.Loc())) |
- atomic.StorePointer(&i.item, unsafe.Pointer(src.Item())) |
+ newloc := src.Loc() |
+ newitem := src.Item() |
+ |
+ i.m.Lock() |
+ defer i.m.Unlock() |
+ i.loc = newloc |
+ i.item = newitem |
} |
const itemLoc_hdrLength int = 4 + 4 + 4 + 4 |
@@ -104,8 +131,7 @@ func (i *itemLoc) write(c *Collection) (err error) { |
return err |
} |
atomic.StoreInt64(&c.store.size, offset+int64(ilength)) |
- atomic.StorePointer(&i.loc, |
- unsafe.Pointer(&ploc{Offset: offset, Length: uint32(ilength)})) |
+ i.setLoc(&ploc{Offset: offset, Length: uint32(ilength)}) |
} |
return nil |
} |
@@ -170,8 +196,7 @@ func (iloc *itemLoc) read(c *Collection, withValue bool) (icur *Item, err error) |
return nil, err |
} |
} |
- if !atomic.CompareAndSwapPointer(&iloc.item, |
- unsafe.Pointer(icur), unsafe.Pointer(i)) { |
+ if !iloc.casItem(icur, i) { |
c.store.ItemDecRef(c, i) |
return iloc.read(c, withValue) |
} |