On Tuesday, 26 September 2017 at 09:10:41 UTC, James Brister
wrote:
I'm pretty new to D, but from what I've seen there are two
modes of using data across threads: (a) immutable message
passing and the new thread copies the data if it needs to be
modified, (b) shared, assuming the data will be modified by
both threads, and the limits that imposes . But why nothing for
passing an object of some sort to another thread with the
ownership moving to the new thread.
If you're talking about the language:
Because D doesn't have any builtin concept of ownership.
If you're talking about Phobos (import std.{...}):
Because a general solution is not a trivial problem (see
Jonathan's answer for more detail).
I suppose this would be hard enforce at the language level, but
wouldn't you want this when trying to pass large-ish data
structures from one thread to another (thinking of a network
server, such as a DHCP server, that has a thread for handling
the network interface and it reads the incoming requests and
then passes off to another thread to handle).
In such server code you're probably better off distributing the
request reading (and potentially even the client socket
accepting) to multiple workers, e.g. having multiple threads (or
processes for that matter, as that can minimize downtime when
combined with process supervision) listening on their own socket
with the same address:port (see SO_REUSEPORT).
If you really want to do it, though, the way I'd start going
about it would be with a classic work queue / thread pool system.
Below is pseudo code showing how to do that for a oneshot request
scenario.
[shared data]
work_queue (synchronize methods e.g. with mutex or use a lockfree
queue)
main thread:
loop:
auto client_socket = accept(...);
// Allocate request on the heap
Request* request = client_socket.readRequest(...);
// Send a pointer to the request to the work queue
work_queue ~= tuple(client_socket, request);
// Poor man's ownership by forgetting about client_socket
and request here
worker thread:
loop:
...
auto job = work_queue.pop();
scope (exit) { close(job[0]); free(job[1]); }
auto response = job[1].handle();
job[0].writeResponse(response);