Possible to pass a member function to spawn?

Sean Kelly sean at invisibleduck.org
Tue Feb 7 15:32:50 PST 2012


On Feb 7, 2012, at 3:09 PM, Manu wrote:

> On 8 February 2012 00:33, Sean Kelly <sean at invisibleduck.org> wrote:
> On Feb 6, 2012, at 1:38 PM, Oliver Puerto wrote:
> 
> > Hello,
> >
> > I'm very new to D. Just started reading "The D programming language". I should read it from beginning to end before posting questions here. I know ... But I'm just too impatient. The issue seems not to be that simple, nevertheless. The code below compiles with Visual Studio.
> >
> > I want to have something like my actor class that I can start running in it's own thread like in Scala or other languages that support actors. So at best, I would like to do something like this:
> >
> >    MyActor myActor = new MyActor();
> >    auto tid = spawn(&start, &myActor.run());
> 
> This should work:
> 
> void runActor(shared MyActor a) { (cast(MyActor)a)).run(); }
> MyActor myActor = new MyActor();
> auto tid = spawn(cast(shared MyActor) myActor, &runActor);
> 
> See, my conclusion is, whenever using this API, you inevitably have dog ugly code. That code is barely readable through the casts... I can only draw this up to faulty API design.
> I understand the premise of 'shared'-ness that the API is trying to assert/guarantee, but the concept is basically broken in the language. You can't use this API at all with out these blind casts, which is, basically, a hack, and I am yet to see an example of using this API 'properly'. The casts are totally self defeating.

In this case, an alternative would be to create the actor in the spawned thread:

void run() {
    auto a = new Actor;
    a.run();
}
spawn(&run);

Regarding shared as it applies to classes… one reason it hasn't been built out in druntime yet is because the original intent was for shared methods to basically end up with compiler-generated memory barriers all over the place and this was sufficiently unappealing that I didn't want to support it.  As far as I'm aware, this is no longer planned, but the transitivity of shared can still make for some weirdness at the implementation level.  For example, if I have:

class Thread {
    pthread_t p;
    shared void detach() {
        pthread_detach(p);
    }
}

Building this yields:

Error: function core.sys.posix.pthread.pthread_detach (_opaque_pthread_t*) is not callable using argument types (shared(_opaque_pthread_t*))
Error: cannot implicitly convert expression (this.p) of type shared(_opaque_pthread_t*) to _opaque_pthread_t*

So I either need to speculatively update a bunch of system API calls to add a 'shared' qualifier to everything I think will always be used in a shared context, or explicitly cast away shared when actually passing these variables to their associated API routines.  Neither option is appealing, so again I haven't done anything regarding shared.


> std.concurrency really should allow unique references to a non-shared type to be passed as well, using something similar to assumeUnique.
> 
> Something like that should exist in the language (... or shared should just not be broken). Using a template like assumeUnique is no better than the ugly cast. What does it offer over a cast?

Only that it isn't a cast, so the receiver routine could be something like:

void run(Unique!MyActor a) { a.run(); }


More information about the Digitalmars-d mailing list