Using net.Stream simultaneously on 2 threads

According to implementation

pub const Stream = struct {
    /// Underlying platform-defined type which may or may not be
    /// interchangeable with a file system file descriptor.
    handle: posix.socket_t,
   ...........................
}

net.Stream is thin socket wrapper.

Does it mean, that after connection, I can simultaneously use it on 2 threads:

  • Writer (main thread)
  • Reader (worker thread)

nope, it doesn’t do any synchronisation for you
std.Thread has some synchronisation types you can use, such as a mutex which is all you need with 2 threads

i hope it will be done on the socket layer

almost certain that’s not the case, you need to add something to keep it synchronised, such as std.Thread.Mutex, which in the case of 2 threads is what you want.

Yes, you can and it’s a pretty standard to do so. Having 2 threads per connection doesn’t scale very well (or even 1 thread per connection), but that’s a separate issue.

2 Likes

Thank you

I need to implement pub/sub communication layer

Internal thread will receive from the stream and send messages to the queue (it supports timeout)

Subsciber will send command usual way and recv messages from the queue.

And of course it’s solution only for the client side

You can even have multiple threads reading and writing from the same socket at the same time. The issue is that write/read aren’t usually atomic (it depends on the platform). So it’s possible for concurrent reads to interleave the data they receive, or concurrent writes to interleave what they write.

It’s easy to see how the Stream’s readAll wouldn’t be safe to call while another thread might also be reading. Or how the Stream’s writeAll wouldn’t be safe to call while another thread might also be writing. But this atomicity issue isn’t restricted to user-space functions like readAll and writeAll, as I believe that, on most platforms, even the underlying read and write have no guarantees about being atomic.

This all holds for std.net.Stream since it’s just a wrapper around the underlying socket - it has no state of its own.

2 Likes

Atomic write will be achieved via mutex

    // Writes the buffer to underlying stream.
    pub fn write(cl: *Client, buffer: []const u8) !void {
        cl.mutex.lock();
        defer cl.mutex.unlock();

        if (cl.connection == null) {
            return ReturnedError.CommunicationFailure;
        }

        try cl.connection.?.writer().writeAll(buffer);
    }

Read from the single stream will be allowed on dedicated thread only

This way pub/sub messages will be safe

sorry if it wasn’t clear, what @karlseguin said is what i was trying to communicate

1 Like