Combining Unique type with concurrency module

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Sep 13 17:11:07 PDT 2015


On 09/13/2015 09:09 AM, Alex wrote:
 > I'm new to this forum so, please excuse me in advance for
 > asking silly questions.

Before somebody else says it: There are no silly questions. :)

 > struct std.typecons.Unique!(S).Unique is not copyable because it is
 > annotated with @disable

I have made the code compile and work (without any thread 
synchronization at all). See the comments with [Ali] annotations:

import std.stdio;
import std.concurrency;
import std.typecons;

void spawnedFunc2(Tid ownerTid)
{
     /* [Ali] Aside: ownerTid is already and automatically
      * available. You don't need to pass it in explicitly. */

     receive(
         /* [Ali] The compilation error comes from Variant, which
          * happens to be the catch all type for concurrency
          * messages. Unfortunately, there are issues with that
          * type.
          *
          * Although implemented as a pointer, according to
          * Variant, a 'ref' is not a pointer. (I am not sure
          * whether this one is a Variant issue or a language
          * issue.)
          *
          * Changing the message to a pointer to a shared
          * object: */
         (shared(Unique!S) * urShared)
         {
             /* [Ali] Because the expression ur.i does not work on
              * a shared object, we will hack it to unshared
              * first. */
             auto ur = cast(Unique!S*)urShared;
             writeln("Recieved the number ", ur.i);
         }
     );
     send(ownerTid, true);
}

static struct S
{
     int i;
     this(int i){this.i = i;}
}

Unique!S produce()
{
     // Construct a unique instance of S on the heap
     Unique!S ut = new S(5);
     // Implicit transfer of ownership
     return ut;
}

void main()
{
     Unique!S u1;
     u1 = produce();
     auto childTid2 = spawn(&spawnedFunc2, thisTid);

     /* [Ali] Cast it to shared so that it passes to the other
      * side. Unfortunately, there is no guarantee that this
      * object is not used by more than one thread. */
     send(childTid2, cast(shared(Unique!S*))&u1);

     /* [Ali] We must wait to ensure that u1 is not destroyed
      * before all workers have finished their tasks. */
     import core.thread;
     thread_joinAll();

     writeln("Successfully printed number.");
}

Note that thread synchronization is still the programmer's responsibility.

 > I'm aware of the fact, that my u1 struct can't be copied, but I don't
 > intend to do so.

Correct.

 > As in the docu stated, I want to lend the struct to the
 > other thread (by using ref), being sure, that any other thread can't
 > access the struct during it is processed by the first one.

There is a misconception. Unique guarantees that the object will not be 
copied. It does not provide any guarantee that only one thread will 
access the object. It is possible to write a type that acquires a lock 
during certain operations but Unique isn't that type.

 > Is such a thing possible?
 > Thanks in advance.
 > Alex

Ali



More information about the Digitalmars-d-learn mailing list