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

Reply via email to