Concurrency Read/Write and Pure

Jonathan M Davis jmdavisProg at gmx.com
Wed Nov 30 20:53:56 PST 2011


On Thursday, December 01, 2011 04:23:39 Adam wrote:
> Howdy.
> 
> So, I'm reading through "The D Programming Language" book, and I had
> some questions on concurrency in D, and maybe with some emphasis on
> programming in general.
> 
> I present my question with a hypothetical case:
>  I have two threads and, ideally, one structure. The structure is
> large enough that passing it in its entirety is non-trivial, and
> that a synchronized understanding of the data at any given point of
> time between the two threads is ideal (that is, it's not desirable
> for one thread to update another with changes to the structure).
>  One thread writes / makes changes to the structure's contents.
>  The other only reads the structure's contents (as well as its
> topology)
> 
> Now, I could make this structure global with respect to both threads
> (shared), which would introduce the need to synchronize access to it
> for both threads (using synchronized, mutexes, etc).
> 
> However, for all intents and purpose, the writing thread "owns" the
> data - it's the only thread allowed to make changes to it.
> 
> Given that, and the guarantees made by "pure," is there a scheme in
> D to fit this explicit one-thread-reads, one-thread-writes scenario
> that doesn't require a mutex / synchronization between the two
> (since only one will be changing it)?

To have an object on two threads without it being shared essentially requires 
that you cast away shared on one or both of the threads, which more or less 
subverts the type system, but it works as long as _you_ guarantee that only 
one thread actually has the object or put whatever else needs to be in place 
to ensure that manipulating it from two or more threads doesn't cause issues 
(such as using mutexes).

If you don't care that the object may not be in a completely up-to-date state 
(that is, if you read it in the reader thread while it's being written to in 
the writer thread), then it's a non-issue, but if you want to make sure that 
the reader thread never reads while the writer thread is writing, then you're 
going to have to use mutexes or synchronized blocks or the like. Otherwise, 
there's nothing which stops the reader thread from reading while the writer 
thread is writing - _especially_ if you've cast away shared, since then the 
compiler treats the object as if it were thread-local. Without that 
synchronization, you have no way of guaranteeing that the writes are 
essentially atomic, and if they're not atomic, then the reader thread can read 
while the writer thread is writing.

Pure really doesn't enter into this at all. A pure function whose parameters 
aren't immutable (or implicitly convertible to immutable) doesn't make any 
guarantees beyond the fact that it can't access global mutable state or call 
any non-pure functions. If all of the parameters are immutable or implicitly 
convertible to immutable, then when multiple calls are made within a single 
expression (and maybe statement - I don't recall for sure, but certainly not 
over multiple statements), only a single call will be made - which is the 
primary optimization that pure provides.

Not only does that have nothing to do with threading, but if the parameters 
are immutable, then you can't use a mutable object with them as you seem to be 
looking to do. And if the parameters are implicitly convertible to immutable 
rather than actually immutable (e.g. with a struct or int or some other value 
type), then a copy would be being made, which doesn't sound like what you're 
trying to do.

Really, to do what you're trying to do should be done with a shared object - 
probably with the type being synchronized (either that, or it needs to use one 
or more mutexes). Pure isn't going to help you.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list