With the current channels implementation, you can implement a basic request-response system between threads by sending an object over a channel that includes (as one of its fields) a channel for sending the response. For example...
type
FooRequest = object
message: string
response: ptr Channel[FooResponse]
FooResponse = object
message: string
This is basically how i was doing thread communication before. But after looking at the new channel implementation, I noticed that one difference is the requirement that data send over channels is isolated. This makes the above impossible since you can't include a ptr or ref type in the object. Is there a better way to do this?
I'm guessing the isolation just means that Nim can guarantee that you don't have any way to use the data after you've sent it. You've essentially "given" that data to the receiving thread and its GC, if you used it afterwards then it wouldn't be able to reason about when to destroy it. Not entirely sure why Channels by themselves can be isolated, almost seems like a bug..
The way I've done channels with a response in the past is to allocate a Request object on the requesters stack, it includes the query, an atomic boolean indicating whether the request is done, and a response field. The response field is non-GCed data, but maybe you could make it work with GCed data as well. A request is then sent by creating the query, then sending a pointer over the channel, the sender then doesn't touch anything in the request object except for the atomic boolean while the responder is working. The responder will copy its request into the area allocated on the requesters stack, and then finally set the atomic to true. When the requester sees the atomic is set it knows that the data in the response field of the object should be safe to read.
This is really a hack using the old channels to pass the pointers around, and the data still has to be copied back. But it works pretty well.