www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Struggling with shared objects

reply "Mike" <mvlipka gmail.com> writes:
Hey, all.

I have just started using D and I'm really loving it, but I have
been caught on a problem.
I am trying to share my Client class to a new thread, and after a
bit of struggling: I finally got the code to compile!

Now I am having a new problem: the moment I call
"client.receive(buf)" I get an error:
D:\D\dmd2\src\phobos\std\concurrency.d(13,13): Error: static
assert  (false || false) is false (StompBroker)

I assume it has something to do with the way I am handling the
shared keyword along with pointers, but I cannot for the life of
me figure this out!

Any help is appreciated. Thank you!

Code: https://github.com/mvlipka/StompBroker
Jan 17 2015
next sibling parent reply "Vlad Levenfeld" <vlevenfeld gmail.com> writes:
That's real weird.
In D:\D\dmd2\src\phobos\std\concurrency.d(13,13)
13,13 isn't a line number
and static assertions should go off during compilation, not 
runtime.
Jan 17 2015
parent reply "Mike" <mvlipka gmail.com> writes:
On Saturday, 17 January 2015 at 21:12:34 UTC, Vlad Levenfeld 
wrote:
 That's real weird.
 In D:\D\dmd2\src\phobos\std\concurrency.d(13,13)
 13,13 isn't a line number
 and static assertions should go off during compilation, not 
 runtime.
It is during compilation. When I run dmd myself, I get this: C:\Users\Michael\Documents\Projects\StompBroker\StompBroker>dmd main.d D:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(165): Error: static ass ert (false || false) is false D:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(634): instantiat ed from here: checkops!(shared(Client*), char[1024]) main.d(11): instantiated from here: receive!(shared(Client*), char[1024])
Jan 17 2015
parent "Mike" <mvlipka gmail.com> writes:
Oh, I said "the moment I call"

I should have reworded that. I meant that the moment I add that 
line to the code, I get the error.

Sorry!
Jan 17 2015
prev sibling parent reply "anonymous" <anonymous example.com> writes:
On Saturday, 17 January 2015 at 21:00:34 UTC, Mike wrote:
 Hey, all.

 I have just started using D and I'm really loving it, but I have
 been caught on a problem.
 I am trying to share my Client class to a new thread, and after 
 a
 bit of struggling: I finally got the code to compile!

 Now I am having a new problem: the moment I call
 "client.receive(buf)" I get an error:
 D:\D\dmd2\src\phobos\std\concurrency.d(13,13): Error: static
 assert  (false || false) is false (StompBroker)

 I assume it has something to do with the way I am handling the
 shared keyword along with pointers, but I cannot for the life of
 me figure this out!

 Any help is appreciated. Thank you!

 Code: https://github.com/mvlipka/StompBroker
I don't get what `auto message = client.receive(buf);` is supposed to call exactly. If you mean to call std.concurrency.receive [1], it's way off. That's what the error message complains about. If you mean to call a method of Client, well it doesn't have a `receive` method. Also, you have too many asterisks (*). Classes already have reference semantics in D. There's no need for `Socket*` or `Client`. Just use `Socket` and `Client`. [1] http://dlang.org/phobos/std_concurrency#.receive
Jan 17 2015
parent reply "Mike" <mvlipka gmail.com> writes:
Ha, I am so stupid! I forgot to call the socket member before 
receive!

Thank you for the help. I have also removed the pointers.

I am now getting this:

C:\Users\Michael\Documents\Projects\StompBroker\StompBroker>dmd 
main.d
main.d(11): Error: None of the overloads of 'receive' are 
callable using a shared object, candidates are:
D:\D\dmd2\windows\bin\..\..\src\phobos\std\socket.d(2897):std.socket.S
cket.receive(void[] 
buf, SocketFlags flags)
D:\D\dmd2\windows\bin\..\..\src\phobos\std\socket.d(2912):std.socket.S
cket.receive(void[] 
buf)
Jan 17 2015
parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Saturday, January 17, 2015 21:56:56 Mike via Digitalmars-d-learn wrote:
 Ha, I am so stupid! I forgot to call the socket member before
 receive!

 Thank you for the help. I have also removed the pointers.

 I am now getting this:

 C:\Users\Michael\Documents\Projects\StompBroker\StompBroker>dmd
 main.d
 main.d(11): Error: None of the overloads of 'receive' are
 callable using a shared object, candidates are:
 D:\D\dmd2\windows\bin\..\..\src\phobos\std\socket.d(2897):std.socket.Socket.receive(void[]
 buf, SocketFlags flags)
 D:\D\dmd2\windows\bin\..\..\src\phobos\std\socket.d(2912):std.socket.Socket.receive(void[]
 buf)
Very little in the standard library is currently going to be usable as shared. The only way that a member function can be called on a shared object is if the function is marked as shared, and pretty much nothing in the standard library is marked with shared. In theory, the idea is that when using shared, you'd use a synchronized class, and the outer layer of shared would get cast away on the member variables inside of the member functions (since the compiler could guarantee that nothing else has access to those member variables), but synchronized classes haven't been implemented, only synchronized functions. So, at present, there's nowhere in the language that implicitly casts away shared. What that means is that if you're using shared, you generally have to do something like shared T mySharedObject = getMySharedObjectFromSomewhere(); synchronized(objImSynchronizingOn) { auto nowUnshared = cast(T)mySharedObject; // do stuff with nowUnshared // make sure that nothing else has access to nowUnshared so that // unlocking it is safe. } // now it's no longer locked, and only the shared reference to the obeject // exists. And that's still an improvement over C++, because your shared code is segregated from your thread-local code, and you're protecting the shared stuff with locks similar to how you'd do in C++, but obviously, it's more annoying and error-prone than we'd like. In most cases, you just don't use shared unless you have to, and then you use the idiom that I just described. And in the case of sockets, you frequently only want them on one thread anyway, so I question that you really want those sockets to be living on a single thread, in which case, they don't need to be shared, but I don't know what you're doing, so having them be shared may be exactly what needs to happen. But regardless, in general, you should use shared as little as possible, and where you do use it, you're either forced to write functions which only operate on shared objects, or you have to cast away shared when the object is protected by a mutex. And really, you should be protecting with a mutex before you operate on it anyway, so the mutex or synchronized block portion of that is normal. It should just be the casting away of shared that's new and annoying if you're new to D. I'd suggest that you read the concurrency chapter in TDPL, since it's mostly correct, and it should give a decent idea of how to deal with threads and concurrency in D. The main problems with that chapter that I recall is that it claims that shared introduces memory barriers (which isn't currently true and will probably never be true due to the overhead that that would incur), and it describes synchronized classes, which we don't currently have (though AFAIK, the plan is still to add them at some point). Right now, we have synchronized functions like Java does, and TDPL specifically says that that's a bad idea and that synchronized classes are better (which may be true, but we don't have them yet). That chapter is one of the few that's available online if you don't own the book: http://www.informit.com/articles/article.aspx?p=1609144 though I'd advise that you pick up the book if you don't have it, since it's quite good and still mostly correct ( http://wiki.dlang.org/Differences_With_TDPL lists most of the differences). - Jonathan M Davis
Jan 17 2015
parent "Mike" <mvlipka gmail.com> writes:
Thank you so much!

I got it all working now.

You're definitely right, that is still easier than C++.
Jan 17 2015