www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - sending shared pointer to struct. message type mismatch

reply jacob <jj75607 gmail.com> writes:
Hello!

I try to send shared pointer to struct:

[code]
import std.stdio;
import std.concurrency;

shared struct S(T, uint M)
{
	T[M] x;
}

shared struct M
{
	int x;
}


private void runner(T)()
{
	shared(T*) s = receiveOnly!(shared(T*))();
	writeln(s.x.length);
	writeln(s.x[0]);
	send(thisTid, true);
}

int main(string[] argv)
{
	alias S!(M, 2) TS;
	alias shared(TS*) PS;

	Tid runnerTid = spawn(&runner!(TS));

	auto s = new shared(TS);
	s.x[0] = M(42);
	send(runnerTid, s);

	bool ok = receiveOnly!bool();

	return 0;
}
[/code]

But after evaluating line "shared(T*) s = 
receiveOnly!(shared(T*))();" I get an exception:

"First-chance exception: std.concurrency.MessageMismatch 
Unexpected message type: expected 'shared(S!(M, 2u)*)', got 
'shared(engine.S!(M, 2u).S)*' at std\concurrency.d(224)"

How can I pass shared pointer to "runner" thread correctly?
Apr 21 2016
next sibling parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/21/16 1:10 PM, jacob wrote:
 import std.stdio;
 import std.concurrency;

 shared struct S(T, uint M)
 {
      T[M] x;
 }

 shared struct M
 {
      int x;
 }


 private void runner(T)()
 {
      shared(T*) s = receiveOnly!(shared(T*))();
      writeln(s.x.length);
      writeln(s.x[0]);
      send(thisTid, true);
 }

 int main(string[] argv)
 {
      alias S!(M, 2) TS;
      alias shared(TS*) PS;

      Tid runnerTid = spawn(&runner!(TS));

      auto s = new shared(TS);
      s.x[0] = M(42);
      send(runnerTid, s);

      bool ok = receiveOnly!bool();

      return 0;
 }
I get strange behavior. Not an error/exception, but basically hung process. I tried modifying different things, and passing other types of messages. Seems almost like the call to send is ignored for sending the s message. Tried various things, but receiveOnly appears broken for me. I've sent messages that should cause an exception and it just hangs. -Steve
Apr 21 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/21/16 1:29 PM, Steven Schveighoffer wrote:

 I get strange behavior. Not an error/exception, but basically hung
 process. I tried modifying different things, and passing other types of
 messages. Seems almost like the call to send is ignored for sending the
 s message.
Nevermind, this is my ignorance. I was unaware that a spawned thread terminating via uncaught exception does nothing. It kind of makes sense, but definitely not what many would expect. -Steve
Apr 21 2016
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 04/21/2016 02:15 PM, Steven Schveighoffer wrote:

 I was unaware that a spawned thread
 terminating via uncaught exception does nothing.

 It kind of makes sense, but definitely not what many would expect.
In case it's useful to others, there is something written about it here: http://ddili.org/ders/d.en/concurrency.html#ix_concurrency.exception,%20concurrency Ali
Apr 21 2016
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
On 21.04.2016 19:10, jacob wrote:
 private void runner(T)()
 {
      shared(T*) s = receiveOnly!(shared(T*))();
This tries to receive a `shared(S!(M, 2)*)`.
      writeln(s.x.length);
      writeln(s.x[0]);
      send(thisTid, true);
Aside: Should be `ownerTid` here, no?
 }

 int main(string[] argv)
Aside: If you don't use them, you don't need to the `int` return type and parameter on main. A `void main()` works just fine.
 {
      alias S!(M, 2) TS;
      alias shared(TS*) PS;
Aside: preferred syntax nowadays is `alias TS = S!(M, 2);`.
      Tid runnerTid = spawn(&runner!(TS));

      auto s = new shared(TS);
This creates a `shared(S!(M, 2))*`, which is not exactly the same as `shared(S!(M, 2)*)`. The pointer is not shared in the former, but it is shared in the latter. I was going to suggest either sending a `shared(TS*)` or receiving a `shared(T)*`. But it looks like you can't send a shared pointer. When I tried, it got turned into a unshared-pointer-to-shared on the way. Changing it to `shared(T)*` on the receiving end works, though. Do that, I guess.
      s.x[0] = M(42);
      send(runnerTid, s);

      bool ok = receiveOnly!bool();

      return 0;
 }
Apr 21 2016
next sibling parent jacob <jj75607 gmail.com> writes:
On Thursday, 21 April 2016 at 17:33:32 UTC, ag0aep6g wrote:
 On 21.04.2016 19:10, jacob wrote:
 I was going to suggest either sending a `shared(TS*)` or 
 receiving a `shared(T)*`. But it looks like you can't send a 
 shared pointer. When I tried, it got turned into a 
 unshared-pointer-to-shared on the way.
Oh that tricky "shared" keyword... Thank you! http://pastebin.com/YkZ3YzKG fixed version here
Apr 21 2016
prev sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 4/21/16 1:33 PM, ag0aep6g wrote:

 This creates a `shared(S!(M, 2))*`, which is not exactly the same as
 `shared(S!(M, 2)*)`. The pointer is not shared in the former, but it is
 shared in the latter.

 I was going to suggest either sending a `shared(TS*)` or receiving a
 `shared(T)*`. But it looks like you can't send a shared pointer. When I
 tried, it got turned into a unshared-pointer-to-shared on the way.
Yes, because Unqual will remove the shared from the type (this is a normalization of sorts, to help this kind of situation).
 Changing it to `shared(T)*` on the receiving end works, though. Do that,
 I guess.
This does and doesn't make sense. If you receive a shared(T)*, you should be able to receive it into a shared(T*). However, it's possible the library doesn't put this together. -Steve
Apr 21 2016