www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Matching with std.concurrency receive

reply Adam <Adam Anizi.com> writes:
Okie, having some trouble trying to do matches against classes /
interfaces with templates using the std.concurrency's receive()
function.

Here's a simple use case I have:

import std.stdio;
import std.concurrency;
import std.variant;

immutable interface BasicType {
}

immutable class SubType : BasicType {
}

immutable class A(T : BasicType) {
}

void main() {
    Tid tid = spawn(&thread);
    immutable A!(SubType) instance = new immutable(A!(SubType))();
    send(tid, instance);
    while (true) {}
}

void thread() {
    receive(
            (A!(BasicType) message)
            {
                writeln("Received");
            },
            (Variant ant)
            {
                writeln(ant.type());
            }
           );
}

Running this outputs the Variant ant's type, so we see that it
"falls through" to that pattern. However, if I switch the match from
BasicType to SubType... it just hangs on me.

What horribly stupid thing am I doing here?
Dec 09 2011
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, December 10, 2011 06:38:19 Adam wrote:
 Okie, having some trouble trying to do matches against classes /
 interfaces with templates using the std.concurrency's receive()
 function.
 
 Here's a simple use case I have:
 
 import std.stdio;
 import std.concurrency;
 import std.variant;
 
 immutable interface BasicType {
 }
 
 immutable class SubType : BasicType {
 }
 
 immutable class A(T : BasicType) {
 }
 
 void main() {
     Tid tid = spawn(&thread);
     immutable A!(SubType) instance = new immutable(A!(SubType))();
     send(tid, instance);
     while (true) {}
 }
 
 void thread() {
     receive(
             (A!(BasicType) message)
             {
                 writeln("Received");
             },
             (Variant ant)
             {
                 writeln(ant.type());
             }
            );
 }
 
 Running this outputs the Variant ant's type, so we see that it
 "falls through" to that pattern. However, if I switch the match from
 BasicType to SubType... it just hangs on me.
 
 What horribly stupid thing am I doing here?
The type must match _exactly_. So, if the type you're passing is immutable(A!SubType), then you need to be receiving immutable(A!SubType). That aside, I'm not sure that receive actually works with classes at the moment. I believe that there are some issues with Variant which make it not work. http://d.puremagic.com/issues/show_bug.cgi?id=7069 - Jonathan M Davis
Dec 09 2011
parent reply Adam <Adam Anizi.com> writes:
Hrm... that's a bit problematic. If I do use the exact match, it seems
to hang / lock up (probably the lack of support for classes?).
However, that's pretty much never the case of what I want to do, since
what I'm trying to do involves passing / accepting an interface and
its implementations.

I guess I can manage this with a static table of operation IDs
pointing to function delegates. Sadness. Haha

Alright, thankee!
Dec 10 2011
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Saturday, December 10, 2011 17:30:50 Adam wrote:
 Hrm... that's a bit problematic. If I do use the exact match, it seems
 to hang / lock up (probably the lack of support for classes?).
 However, that's pretty much never the case of what I want to do, since
 what I'm trying to do involves passing / accepting an interface and
 its implementations.
 
 I guess I can manage this with a static table of operation IDs
 pointing to function delegates. Sadness. Haha
It probably _should_ accept interfaces for classes and the like, but I don't think that it works properly for classes at the moment (due to issues with Variant), and in my experience, I've had use the _exact_ type, as annoying as that may be. For instance, if IIRC, I tried to pass a string which happened to be immutable, and when I tried to receive string on the other end, it wouldn't work until I changed it to receive an immutable string. If you have a type A which you think definitely should be receivable as type B on the other side, and it doesn't work, please submit a bug report: d.puremagic.com/issues . It's possible that you're misunderstanding something, but it's also definitely a possibility that receive just doesn't work right in some cases (e.g. far too strict). A bug report increases the chances of it getting fixed. - Jonathan M Davis
Dec 10 2011
prev sibling parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Sat, Dec 10, 2011 at 1:38 PM, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Saturday, December 10, 2011 17:30:50 Adam wrote:
 Hrm... that's a bit problematic. If I do use the exact match, it seems
 to hang / lock up (probably the lack of support for classes?).
 However, that's pretty much never the case of what I want to do, since
 what I'm trying to do involves passing / accepting an interface and
 its implementations.

 I guess I can manage this with a static table of operation IDs
 pointing to function delegates. Sadness. Haha
It probably _should_ accept interfaces for classes and the like, but I don't think that it works properly for classes at the moment (due to issues with Variant), and in my experience, I've had use the _exact_ type, as annoying as that may be. For instance, if IIRC, I tried to pass a string which happened to be immutable, and when I tried to receive string on the other end, it wouldn't work until I changed it to receive an immutable string. If you have a type A which you think definitely should be receivable as type B on the other side, and it doesn't work, please submit a bug report: d.puremagic.com/issues . It's possible that you're misunderstanding something, but it's also definitely a possibility that receive just doesn't work right in some cases (e.g. far too strict). A bug report increases the chances of it getting fixed. - Jonathan M Davis
With classes, Variant currently can't handle immutability. Passing shared objects is fine, and casting works as a workaround. The bug report also has a workaround that's fairly easy to add to std.variant, but it sounds like the current std.variant isn't going to get fixed (just the replacement that's in development). The thing that seems to be confusing about message passing is that we have no dynamic pattern matching (and that's not because of receive, it's because of Variant), so all type matching comes from templates and checking types for equality. If you pass in a reference of type Object, it doesn't matter what type the actual object is, you can only match it as Object when receiving it. This may or may not be unavoidable - if we can implement dynamic type matching, classes will need to special cased in the Variant code (because you can't dynamically typecheck a struct or primitive). This is probably worth asking Rob Jacques about, since he's developing the std.variant replacement.
Dec 10 2011
parent Adam <Adam anizi.com> writes:
Hm.. so I tried another approach, which would be to send the type
name as a string, then use Object.factory to instantiate that (ugly,
but whatever). Had a few problems with that, then just reduced it to
a non-thread case:


import std.stdio;

immutable interface BasicType {
}

immutable class SubType : BasicType {
}

immutable class A(T : BasicType) {
}

void main() {
    immutable A!(SubType) instance = new immutable(A!(SubType))();
    writeln("Type name is " ~ instance.classinfo.name);
    Object object = Object.factory(instance.classinfo.name);
    if (object) {
        writeln("Created");
    } else {
        writeln("Failed");
    }
}

This returns "Failed." So, I thought I'd just provide Object.factory
"hello.A" (since hello is the module name and is what is printed
from the writeln). Still no good.

Any thoughts?
Dec 10 2011