-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(cbindings): Thread-safe libwaku. WakuNode instance created directly from the Waku Thread #1957
Conversation
builder.withRecord(record) | ||
builder.withNetworkConfiguration(netConfig) | ||
builder.withSwitchConfiguration( | ||
maxConnections = some(50.int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be really hardcoded? Can you at least make it a constant?
if newNodeRes.isErr(): | ||
return err(newNodeRes.error) | ||
|
||
node[] = newNodeRes.get() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this notation (the []
) mean/do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the comments! I'll fix them asap.
This []
is used for ptr
types. I understand the []
operator as a way to dereference the ptr, i.e. a way to access the value or object it points to.
Something interesting I've learned recently:
ref obj A | ptr A |
---|---|
Points to data stored in the heap | Points to data stored either in the heap or stack |
GC'ed | The developer should take care of allocating and deallocating manually |
No thread-safe | Thread-safe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fwiw, []
is also used to dereference ref
- in this sense, ref
and ptr
is similar - they differ in that ref
is a reference-counted pointer and ptr
is a "manual" pointer - for example:
proc myFunction(v: int) = echo v
var a = new int # this returns a `ref int`
let b = addr a[] # this returns a `ptr int` pointing to the same memory location as `a`
myFunction(a[]) # call the function with a dereferenced value
myFunction(b[])
a = nil # this removes the reference that `a` was holding - `b` now points to a memory location that the GC will reclaim - it's a dangling pointer
nim "sometimes" dereferences ref
automatically as part of the language semantics - I find this to mostly be a misfeature that leads to more problems than it solves -> I always put []
when using either of ptr
and ref
(to remind myself that both could be nil
for example)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you very much!
library/libwaku.nim
Outdated
let createThRes = waku_thread.createWakuThread() | ||
if createThRes.isErr(): | ||
let msg = "Error in createWakuThread: " & $createThRes.error | ||
onErrCb(unsafeAddr msg[0], cast[csize_t](len(msg))) | ||
return RET_ERR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let createThRes = waku_thread.createWakuThread() | |
if createThRes.isErr(): | |
let msg = "Error in createWakuThread: " & $createThRes.error | |
onErrCb(unsafeAddr msg[0], cast[csize_t](len(msg))) | |
return RET_ERR | |
let createTh = waku_thread.createWakuThread().valueOr: | |
let msg = "Error in createWakuThread: " & $error | |
onErrCb(unsafeAddr msg[0], cast[csize_t](len(msg))) | |
return RET_ERR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
or.. if this is Result[void, E]
, use isOkOr:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super interesting! Thanks for that! Notice that I will only apply that to this snippet and I'm planning to extend this approach to further places at nwaku
.
|
||
of START_NODE: | ||
waitFor node.start() | ||
waitFor node[].start() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
{.async.}
functions must never call waitFor
- instead, they should use await
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah yes, my bad!
|
||
method process*(self: NodeLifecycleRequest, | ||
node: WakuNode): Future[Result[string, string]] {.async.} = | ||
node: ptr WakuNode): Future[Result[string, string]] {.async.} = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WakuNode
is a ref object
- the previous code without the ptr
was correct - a consequence is that process
is not a "thread-safe" function - it can only be called from the thread that created the WakuNode
instance (ie the processing loop below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, I see now - this looks as if you wanted to return the node instance and async
prevents var
from being used - ok, ptr
can be used as a workaround for that limitation as long as you keep in mind that a ptr might become dangling - this is a bit of a general problem here and for this PR it's an ok tradeoff to improve the status quo - later, I would probably look for solutions that avoid this quirk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, the idea of using ptr
was to alter the node instance:
nwaku/library/waku_thread/waku_thread.nim
Line 48 in f29105b
var node: WakuNode |
This instance will live enough for all the calls to any process
proc and will always be owned by the Waku Thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
I will merge this as we have another PR that is blocked by that one. |
Description
This is aimed at having a safer c-bindings
libwaku
. With that regard, given that the WakuNode is a GC-managed type, we need to make sure the instance of the WakuNode is directly created from within the Waku Thread itself.note: each
ref
,seq[T]
, orstring
are GC-manged typesChanges
CREATE_NODE
operation type.CREATE_NODE
req to the Waku Thread so that it creates the Waku Node instance.make cwaku_example
actually compiles.Issue
#1878