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
Converting WrenHandle to a foreign object's data #592
Comments
a) yes you have to garantee life time
And make the holder object to handle Foo*. |
I thought about using the stack/slot array, but this is required in some threaded code so it isn't safe to do that. Embedding the WrenHandle inside it's own foreign object... that's interesting indeed. |
Well since you said you are in threaded code, then you will surely have to make some synchronisation around destruction, and don't try to call wren code directly from worker thread. All the trivial threaded stuff... |
It's my first time writing serious threaded code so that's a whole learning experience, but yes, there is a separation of concerns, and I'm definitely not calling Wren from the threads. I wanted asynchronous IO for my game engine, so the threads are handling the IO operations, and the main thread runs the wren vm. The difficulty is getting the results back to wren safely. At the moment, I'm basically creating a I think your Foo example above would be suitable for that. |
I would probably have done it the other way, or at least think the other
way. Made the main thread responsible of the IO, and made wren a secondary
thread.
While in design it doesn't change much, your main thread could still answer
to system events and kill the interpreter.
|
How would that work? Wren is doing the majority of the game engine
execution work, so you can't really defer it to a secondary thread...
…On Fri, 3 Aug 2018 at 15:44 Michel Hermier ***@***.***> wrote:
I would probably have done it the other way, or at least think the other
way. Made the main thread responsible of the IO, and made wren a secondary
thread.
While in design it doesn't change much, your main thread could still answer
to system events and kill the interpreter.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#592 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABYQrwSn0eo9RdX2zgiBQZsTQhCaRz8Mks5uNGHfgaJpZM4VtI8d>
.
|
The "main" thread is a concept. If you enter I don't see the need to make it more complicated than it is, though. It's fine to keep it that way with a worker thread for IO. This is very common. Typically for async IO you just need a simple array of events/messages with a lock on adding to it. It doesn't have to be fancy (so no need for lock free) since async IO is not a 10000 per frame type of operation that needs low contention. Find or make a simple thread safe queue or list, a mutex on adding to the list is fine. Reading shared data from multiple threads is fine, only writing causes the concern. Then send the payload into the queue, and the main thread will be checking it each tick or periodically (polled) for new events. When an event comes in, now it's handled on the right thread. You can grab the foreign out of the payload (assuming it's a call handle) and use it safely since you're back on main. |
Right. So assuming I've understood the whole conversation correctly, I can dispatch the IO task to my pool of threads. The task payload can contain the foreign object pointer with safety (having made a WrenHandle earlier), and then on a thread, modify the object data, post the results to the main thread and release the handle. Assuming that makes sense, thank you both for your help. |
Not sure about modifying the object part, if you mean modifying the data owned by wren - that wouldn't be the right thing to do from another thread. A handle is not a lock on the data right. |
Well there is a little thing to nuance, on unix systems (at least) the main/root thread is the only responsible to handle some process critical signals. This is why I think it is better to offload the wren thread to its own thread, so it doesn't need to deal with that directly. |
If I can't use the foreign data pointer directly from a thread, I'll just have to defer the result writing until the task completed and returns to the main thread. Not the end of the world, just an inconvenience. |
it just depends who owns the data and how it's allocated, the payload going back and forth can be for example two pointers, one for the block of data that the IO operation interacts with on both sides (making the payload itself the owner) and the handle. If you allocate that block via wren (say a string as bytes) then you don't want to touch it via threads. If you allocate in the worker thread and the receiving thread just reads / copies it to wren that's fine. If the data is allocated inside the payload itself same thing, writes are not overlapping with reads (because you'd never read a payload from main thread while it's in the worker thread, it tells you when it's done and then you read it). I think if you use |
I would go even deeper, make it work single thread and then try to make it
multithread.
|
Thanks all for your advice. I've managed to get to a point where I'm only holding onto a WrenHandle* and then using the Slot array on the main thread to retrieve a foreign data pointer from the Handle, which made me notice a slightly interesting thing: There doesn't seem to be a safe way to release a WrenHandle that a foreign class object is holding, without doing it pre-emptively. My hope was to release it during my finalizer method (despite the warning that you have limited access to the VM). On the otherhand, not releasing the Handle doesn't seem to cause any errors or other issues, so I suspect it's just a wasteful memory leak until the VM shuts down. I guess the fact that I don't get an error or warning is a bug, given the explanation in the documentation. |
There is an error if you're in debug mode |
That would answer it. Need to figure out a neater solution to that then. :/ |
If you hit these kind of problems, it means that your data is either to
much complicated, or requires smart pointer in your C/C++ code.
By to much complicated, I mean maybe there is a way to isolate the data
more so it can be freed without interdependency. Else if there are
mendatory cross referencing, you need an extra smart pointer layer. It
means that wren object old the smartpointer not the data directly.
I may have an alternative solution in some future, but I doubt Bob will
ever accept it, as it duplicate wren handles to some extent: Adding
refcounting to Wren object. It might not be an ideal solution, as it might
open a huge new can of worms thought.
|
If I have a foreign method which is being passed a foreign object, then:
a) Does it make sense to create and hold onto a WrenHandle* for it, especially if I want to return the object later as part of a foreign getter
and b) Can I extract or modify the foreign data from the WrenHandle*?
The text was updated successfully, but these errors were encountered: