mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-08-02 04:43:16 +00:00
exper with custom sharedptr -- are we keeping a sig ref somewhere?
This commit is contained in:
parent
18b0d33ac7
commit
08c4a936ad
@ -32,7 +32,7 @@ method has*(
|
||||
|
||||
try:
|
||||
has(ret, sig, self.tds, key)
|
||||
await wait(sig)
|
||||
wait(sig)
|
||||
finally:
|
||||
discard # ret.release()()
|
||||
|
||||
@ -47,7 +47,7 @@ method delete*(
|
||||
|
||||
try:
|
||||
delete(ret, sig, self.tds, key)
|
||||
await wait(sig)
|
||||
wait(sig)
|
||||
finally:
|
||||
discard # ret.release()()
|
||||
|
||||
@ -78,7 +78,7 @@ method get*(
|
||||
|
||||
try:
|
||||
get(ret, sig, self.tds, key)
|
||||
await wait(sig)
|
||||
wait(sig)
|
||||
finally:
|
||||
discard # ret.release()()
|
||||
|
||||
@ -90,13 +90,16 @@ method put*(
|
||||
data: seq[byte]
|
||||
): Future[?!void] {.async.} =
|
||||
|
||||
let (ret, sig) = await newThreadResult(void)
|
||||
var ret: TResult[void]
|
||||
block:
|
||||
let (rets, sig) = await newThreadResult(void)
|
||||
ret = rets
|
||||
|
||||
try:
|
||||
put(ret, sig, self.tds, key, data)
|
||||
await wait(sig)
|
||||
finally:
|
||||
discard # ret.release()()
|
||||
try:
|
||||
put(ret, sig, self.tds, key, data)
|
||||
wait(sig)
|
||||
finally:
|
||||
discard # ret.release()()
|
||||
|
||||
return ret.convert(void)
|
||||
|
||||
@ -145,7 +148,7 @@ method query*(
|
||||
if not iter[].it.finished:
|
||||
iterWrapper.readyForNext = false
|
||||
query(ret, sig, self.tds, iter)
|
||||
await wait(sig)
|
||||
wait(sig)
|
||||
iterWrapper.readyForNext = true
|
||||
# echo ""
|
||||
# print "query:post: ", ret[].results
|
||||
|
||||
@ -30,15 +30,6 @@ type
|
||||
## SharedPtr that allocates a shared buffer and keeps the
|
||||
## memory allocated until all references to it are gone.
|
||||
##
|
||||
## Important:
|
||||
## On `refc` that "internal" destructors for ThreadResult[T]
|
||||
## are *not* called. Effectively limiting this to 1 depth
|
||||
## of destructors. Hence the `threadSafeType` marker below.
|
||||
##
|
||||
## Edit: not sure this is quire accurate, but some care
|
||||
## needs to be taken to verify the destructor
|
||||
## works with the specific type.
|
||||
##
|
||||
## Since ThreadResult is a plain object, its lifetime can be
|
||||
## tied to that of an async proc. In this case it could be
|
||||
## freed before the other background thread is finished.
|
||||
|
||||
@ -77,22 +77,52 @@ proc release*(sig: ThreadSignalPtr) {.raises: [].} =
|
||||
signalPoolFree.incl(sig)
|
||||
# echo "free:signalPoolUsed:size: ", signalPoolUsed.len()
|
||||
|
||||
|
||||
type
|
||||
SignalObj* = object
|
||||
val*: ThreadSignalPtr
|
||||
SharedSignalPtr* = object
|
||||
cnt: ptr int
|
||||
buf*: ThreadSignalPtr
|
||||
|
||||
SharedSignalPtr* = SharedPtr[SignalObj] ##\
|
||||
|
||||
proc `=destroy`*(sig: var SignalObj) =
|
||||
echo "FREE SIG! ", sig.val.pointer.repr
|
||||
sig.val.release()
|
||||
proc `$`*(data: SharedSignalPtr): string =
|
||||
if data.buf.isNil:
|
||||
result = "nil"
|
||||
else:
|
||||
result = data.buf.pointer.repr
|
||||
|
||||
proc `=destroy`*(x: var SharedSignalPtr) =
|
||||
if x.buf != nil and x.cnt != nil:
|
||||
let res = atomicSubFetch(x.cnt, 1, ATOMIC_ACQUIRE)
|
||||
if res == 0:
|
||||
# for i in 0..<x.len: `=destroy`(x.data[i])
|
||||
echo "SIGNAL: FREE: ", repr x.buf.pointer, " ", x.cnt[]
|
||||
deallocShared(x.buf)
|
||||
deallocShared(x.cnt)
|
||||
else:
|
||||
echo "SIGNAL: decr: ", repr x.buf.pointer, " ", x.cnt[]
|
||||
|
||||
proc `=copy`*(a: var SharedSignalPtr; b: SharedSignalPtr) =
|
||||
# do nothing for self-assignments:
|
||||
if a.buf == b.buf: return
|
||||
`=destroy`(a)
|
||||
discard atomicAddFetch(b.cnt, 1, ATOMIC_RELAXED)
|
||||
a.buf = b.buf
|
||||
a.cnt = b.cnt
|
||||
echo "SIGNAL: Copy: repr: ", b.cnt[],
|
||||
" ", repr a.buf.pointer,
|
||||
" ", repr b.buf.pointer
|
||||
|
||||
proc `incr`*(a: SharedSignalPtr) =
|
||||
echo "SIGNAL: incr: ", atomicAddFetch(a.cnt, 1, ATOMIC_RELAXED)
|
||||
|
||||
proc newSharedSignalPtr*(): Future[SharedSignalPtr] {.async, raises: [].} =
|
||||
let ts = await getThreadSignal()
|
||||
return newSharedPtr(SignalObj(val: ts))
|
||||
result.cnt = cast[ptr int](allocShared0(sizeof(result.cnt)))
|
||||
result.buf = await getThreadSignal()
|
||||
|
||||
proc fireSync*(sig: SharedSignalPtr): Result[bool, string] =
|
||||
sig[].val.fireSync()
|
||||
template fireSync*(sig: SharedSignalPtr): untyped =
|
||||
let ts: ThreadSignalPtr = sig.buf
|
||||
ts.fireSync()
|
||||
|
||||
proc wait*(sig: SharedSignalPtr): Future[void] =
|
||||
sig[].val.wait()
|
||||
template wait*(sig: SharedSignalPtr): untyped =
|
||||
let ts: ThreadSignalPtr = sig.buf
|
||||
await ts.wait()
|
||||
|
||||
@ -35,64 +35,59 @@ suite "Test Basic ThreadProxyDatastore":
|
||||
check res1.isOk
|
||||
# print "res1: ", res1
|
||||
|
||||
test "check get":
|
||||
# echo "\n\n=== get ==="
|
||||
let res2 = await sds.get(key1)
|
||||
check res2.get() == data
|
||||
var val = ""
|
||||
for c in res2.get():
|
||||
val &= char(c)
|
||||
# print "get res2: ", $val
|
||||
# test "check get":
|
||||
# # echo "\n\n=== get ==="
|
||||
# let res2 = await sds.get(key1)
|
||||
# check res2.get() == data
|
||||
# var val = ""
|
||||
# for c in res2.get():
|
||||
# val &= char(c)
|
||||
# # print "get res2: ", $val
|
||||
|
||||
|
||||
# echo "\n\n=== put cancel ==="
|
||||
# # let res1 = await sds.put(key1, "value for 1".toBytes())
|
||||
# let res3 = sds.put(key1, "value for 1".toBytes())
|
||||
# res3.cancel()
|
||||
# # print "res3: ", res3
|
||||
# suite "Test Basic ThreadProxyDatastore":
|
||||
|
||||
suite "Test Basic ThreadProxyDatastore":
|
||||
# var
|
||||
# memStore: MemoryDatastore
|
||||
# ds: ThreadProxyDatastore
|
||||
# key = Key.init("/a/b").tryGet()
|
||||
# bytes = "some bytes".toBytes
|
||||
# otherBytes = "some other bytes".toBytes
|
||||
|
||||
var
|
||||
memStore: MemoryDatastore
|
||||
ds: ThreadProxyDatastore
|
||||
key = Key.init("/a/b").tryGet()
|
||||
bytes = "some bytes".toBytes
|
||||
otherBytes = "some other bytes".toBytes
|
||||
# setupAll:
|
||||
# memStore = MemoryDatastore.new()
|
||||
# ds = newThreadProxyDatastore(memStore).expect("should work")
|
||||
|
||||
setupAll:
|
||||
memStore = MemoryDatastore.new()
|
||||
ds = newThreadProxyDatastore(memStore).expect("should work")
|
||||
# teardownAll:
|
||||
# (await memStore.close()).get()
|
||||
|
||||
teardownAll:
|
||||
(await memStore.close()).get()
|
||||
# basicStoreTests(ds, key, bytes, otherBytes)
|
||||
|
||||
basicStoreTests(ds, key, bytes, otherBytes)
|
||||
# suite "Test Query":
|
||||
# var
|
||||
# mem: MemoryDatastore
|
||||
# sds: ThreadProxyDatastore
|
||||
|
||||
suite "Test Query":
|
||||
var
|
||||
mem: MemoryDatastore
|
||||
sds: ThreadProxyDatastore
|
||||
# setup:
|
||||
# mem = MemoryDatastore.new()
|
||||
# sds = newThreadProxyDatastore(mem).expect("should work")
|
||||
|
||||
setup:
|
||||
mem = MemoryDatastore.new()
|
||||
sds = newThreadProxyDatastore(mem).expect("should work")
|
||||
# queryTests(sds, false)
|
||||
|
||||
queryTests(sds, false)
|
||||
# test "query iter fails":
|
||||
|
||||
test "query iter fails":
|
||||
# expect FutureDefect:
|
||||
# let q = Query.init(key1)
|
||||
|
||||
expect FutureDefect:
|
||||
let q = Query.init(key1)
|
||||
# (await sds.put(key1, val1)).tryGet
|
||||
# (await sds.put(key2, val2)).tryGet
|
||||
# (await sds.put(key3, val3)).tryGet
|
||||
|
||||
(await sds.put(key1, val1)).tryGet
|
||||
(await sds.put(key2, val2)).tryGet
|
||||
(await sds.put(key3, val3)).tryGet
|
||||
|
||||
let
|
||||
iter = (await sds.query(q)).tryGet
|
||||
res = (await allFinished(toSeq(iter)))
|
||||
.mapIt( it.read.tryGet )
|
||||
.filterIt( it.key.isSome )
|
||||
# let
|
||||
# iter = (await sds.query(q)).tryGet
|
||||
# res = (await allFinished(toSeq(iter)))
|
||||
# .mapIt( it.read.tryGet )
|
||||
# .filterIt( it.key.isSome )
|
||||
|
||||
check res.len() > 0
|
||||
# check res.len() > 0
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user