Combining Unique type with concurrency module

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Sep 14 01:08:34 PDT 2015


On 09/14/2015 12:07 AM, Alex wrote:

 > Do you have a hint how to create such a type? The needed operation is
 > "onPassingTo" another thread. So the idea is to create a resource, which
 > is not really shared (a question of definition, I think), as it should
 > be accessible only from one thread at a time.
 > But there is a "main" thread, from which the resource can be lent to
 > "worker" threads and there are "worker" threads, where only one worker
 > can have the resource at a given time.

Here is an unpolished solution that enforces that the thread that is 
using it is really its owner:

struct MultiThreadedUnique(T) {
     Tid currentOwner;
     Unique!T u;

     this(Unique!T u) {
         this.u = u.release();
         this.currentOwner = thisTid;
     }

     void enforceRightOwner() {
         import std.exception;
         import std.string;
         enforce(currentOwner == thisTid, format("%s is the owner; not %s",
                                                 currentOwner, thisTid));
     }

     ref Unique!T get() {
         enforceRightOwner();
         return u;
     }

     void giveTo(Tid newOwner) {
         enforceRightOwner();
         currentOwner = newOwner;
     }
}

The entire program that I tested it with:

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

void spawnedFunc2(Tid ownerTid)
{
     receive(
         (shared(MultiThreadedUnique!S) * urShared)
         {
             auto ur = cast(MultiThreadedUnique!S*)urShared;
             writeln("Recieved the number ", ur.get().i);
             ur.giveTo(ownerTid);
         }
     );
     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;
}

struct MultiThreadedUnique(T) {
     Tid currentOwner;
     Unique!T u;

     this(Unique!T u) {
         this.u = u.release();
         this.currentOwner = thisTid;
     }

     void enforceRightOwner() {
         import std.exception;
         import std.string;
         enforce(currentOwner == thisTid, format("%s is the owner; not %s",
                                                 currentOwner, thisTid));
     }

     ref Unique!T get() {
         enforceRightOwner();
         return u;
     }

     void giveTo(Tid newOwner) {
         enforceRightOwner();
         currentOwner = newOwner;
     }
}

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

     u1.giveTo(childTid2);
     send(childTid2, cast(shared(MultiThreadedUnique!S*))&u1);

     import core.thread;
     thread_joinAll();

     writeln("Successfully printed number.");
     auto u2 = &u1.get();
}

Ali



More information about the Digitalmars-d-learn mailing list