Use zio, as the evented io, for communicating with the evented io from threaded io, and also for debug_io. std.Io.Mutex used through zio will work no matter if you are in zio’s runtime or any other thread.
If you don’t know the implementations that share the data, then you do need some synchronisation that works across them, which could be another Io though, know that only Threaded qualifies for that currently (ignoring 3rd party Io).
You could also use something outside any Io implementation. Regardless the synchronisation will never be ideally optimal.
It is also possible that you one, and which, of the existing Io qualifies, you could just use that instead creating/using another.
It’s true that this is probably a blind spot in the design of std.Io currently.
One usecase I have for that is a subsystem somewhere that relies on a thread pool to do some work. I’d like to have cross-io synchronization between the thread pool io and the main io (that can be evented or threaded).
for simple access synchronization you can use Mutex with the same io(choice evented only or threaded only) see above advice of @vulpesx , regarding Cancel - use uncancelable lock
for more advcanced case i think there is not generic solution
elaborate please
I’m sorry for being spammy, but I really recommend you to give zio a try. It’s built explicitly for the model that you have evented I/O for your application, but you can delegate some work to a thread pool (zio.spawnBlocking/zio.blockInPlace). It’s what people are used to in Tokio, asyncio, etc.
For my own applications, I use the zio APIs internally, and std.Io only when I need to integrate external library.
There is this ticket opened by Andrew, as a response to me pointing our why I think zio APIs are better for app development than std.Io, https://codeberg.org/ziglang/zig/issues/31112
I don’t think there will ever be an universal solution for cross-io communication.
That does not work. If you call mutex.lock(threaded_io) inside an event loop, you will block the event loop. You can do that for short critical sections, but definitely don’t do that for queues, condition variables anything that actually needs to wait.
That is precisely why it implements the std.Io interface, so you can use it as std.Io with extra stuff that is not in std.Io.
For example, if you want to use std.Io.Threaded and have additional thread pool, will need to build the thread pool on top of std.Io.Threaded (not any std.Io, this one in particular) and then depend on the fact that you can use std.Io.Queue across the io instances, because their synchronization primitives are compatible. It will even work across std.Io.Threaded and std.Io.Evented (when finished), but only on Linux, because they both use Linux futexes.
As I said, I really doubt there will ever be an universal solution, this will always depend on the particular implementations you are using.
I don’t think that’s true. As long as the evented side of std.Io is cooperative, not preemptive, you need multiple executors for different kind of work. Java (virtual threads) and Go (goroutines) get away with just a single executor, because they can preempt long running CPU tasks. That requires language changes and accepting the performance penalties it brings. If you only have cooperative evented I/O, you need to mindful of not blocking the event loop.
Is this a theoretical discussion? The problem could be easily solved, if the architecture of the std.Io was different. If you look at how I designed zio, I essentially have both threaded and evented backends and they naturally coexist. The problem is that e.g. std.Io.Mutex directly uses futexes from the Io implementation, but it doesn’t have to he that way. std.Io could require the implementation to provide a “waiter” abstraction and implement mutex in term of wait queues, which is how it’s typically done in the kernel of operating systems. Heck, it could even build the waiter out of the current futexes without changes to the vtable. Then all the mutexes would suddenly become compatible. Do the same treatment for std.Io.Conditon and you enable the way for cross-io std.Io.Queue which is enough for most communication. I’d even go as far as to say that this is an easy problem to solve, it’s just that there would have to be interest in solving it.
Given the bugs I’ve recently found in the stdlib sync primitives, I might create a library that uses the current interface, and provides cross-io synchronization primitives.
Absolutely not - most networked servers are mix of Threaded processing and Evented network.
But in current situation I should to solve it via workarounds
How to raise/get attention of io architects?
I can understand “now it is not right time for nework”.
Question to io architects - When will be right time to provide threaded-evented coexistence?
As far as I understand your solution - it’s special Io just for sync primitives - the rest of vtable entries - 'notimplemented"