Socket and spawn()

Jonathan M Davis newsgroup.d at jmdavisprog.com
Fri May 31 16:59:08 UTC 2024


On Friday, May 31, 2024 10:07:23 AM MDT Andy Valencia via Digitalmars-d-learn 
wrote:
> I'm coding a server which takes TCP connections.  I end up in the
> main thread with .accept() which hands me a Socket.  I'd like to
> hand this off to a spawn()'ed thread to do the actual work.
>
>      Aliases to mutable thread-local data not allowed.
>
> Is there some standard way to get something which _isn't_ in TLS?
>   Or do I have to drop back to file descriptors and do my own
> socket handling?
>
> TIA,
> Andy

Strictly speaking, unless you're dealing with a module or static-level
variable, the object is not in TLS. It's treated as thread-local by the type
system, and the type system will assume that no other thread has access to
it, but you can freely cast it to shared or immutable and pass it across
threads. It's just that it's up to you to make sure that you don't have a
thread-local reference to shared data that isn't protected in a fashion that
accessing the thread-local references is guarantee to be thread-safe (e.g.
the appropriate mutex has been locked).

So, if you're just passing it to another thread, and that other thread is
all that uses the object, then you would temporarily cast it to shared or
immutable, give it to the other thread, and then that thread would cast it
back to thread-local to use it, and the original thread would have nothing
to do with it any longer.

On the other hand, if you're actively sharing an object across threads, then
you cast it to shared and give it to the other thread. But then you have to
use an appropriate thread-synchronization mechanism (likely a mutex in the
case of a socket) to ensure that accessing the object is thread-safe.

So, typically, you would lock a mutex to ensure that no other thread is
accessing the object, and then you temporarily cast away shared while the
object is protected by the mutex so that you can do whatever you need to do
with the object, and once you're ready to release the mutex, you make sure
that no thread-local references to the object remain before releasing the
mutex. So, any code actually operating on the object would do so while it's
typed as thread-local, and the compiler would complain if you accidentally
accessed it through the shared referenc to the data (though the compiler
doesn't currently catch all such cases - the -preview=nosharedaccess switch
turns on more of the checks, and that's supposed to be become the default
eventually, but it hasn't yet).

In any case, you can freely cast between thread-local and shared. It's just
that you need to be sure that when you do that, you're not violating the
type system by having a thread-local reference to shared data access that
shared data without first protecting it with a mutex. And that typically
means not having any thread-local references to the shared data except when
the mutex is locked. But if all you're doing is passing an object across
threads, then it's pretty straightforward, since you just cast it to shared
or immutable to be able to pass it across threads and then cast back to
thread-local on the other side to use it as normal again (you just need to
make sure that you don't leave a reference to the data on the original
thread when you do that).

- Jonathan M Davis





More information about the Digitalmars-d-learn mailing list