www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - shared and cryptic error messages

reply Jose Armando Garcia <jsancio gmail.com> writes:
import std.stdio;

class B
{
  private File file;
}
synchronized class A
{
  private File file;
}

void main()
{
}

/usr/include/d/dmd/phobos/std/stdio.d(292): Error: destructor
std.stdio.File.~this () is not callable using argument types ()

Why am I getting this error? I suspect that synchronized is the
problem. How do I get around this error? Does this mean that
synchronized classes are not allowed to have as member
unsynchronized/regular classes? Has anyone tried to write a
multithreaded application using D? Why is the error showing up in
std/stdio.d and not in my file? Can anyone point me to a decent
documentation of how "shared" works? I have read chapter 13 of The D
Programming Language and it is not sufficient for the level of
understanding I seek.

That is a lot of question. Hopefully I get answer to at least one.
Mar 30 2011
parent reply Jason House <jason.james.house gmail.com> writes:
Jose Armando Garcia Wrote:

 Why am I getting this error? I suspect that synchronized is the
 problem. 
A synchronized class is implicitly shared and most of the methods are synchronized. I say most because at a minimum, the constructor isn't synchronized on anything. As you probably know shared is transitive, so all members are implicitly shared as well.
 How do I get around this error?
That's not easy to answer... To get the compiler to shut up, you can copy and paste FILE's destructor and mark it as shared. Of course, every method call to your file will similarly required shared methods. If you make no copies of the file object, and all accesses are from within your synchronized methods, you can probably cast away shared while making the method calls. Of course, the common theme here is that you're verifying the multi-threaded safety of all this stuff along the way. If you're not comfortable doing that, then you probably want to do another design that you can prove works.
 Does this mean that
 synchronized classes are not allowed to have as member
 unsynchronized/regular classes?
As I said above, shared is transitive. It's implicit that all members are shared even though you don't mark them as such. No shared objects can have non-shared members. If there are parts that are not accessed by more than one thread, you can either restructure your code a bit, or make liberal use of casts.
 Has anyone tried to write a
 multithreaded application using D?
Yes, and even succeeded :)
 Why is the error showing up in
 std/stdio.d and not in my file?
It's an awful error message. I complained about it back in 2009: http://d.puremagic.com/issues/show_bug.cgi?id=3642 When this kind of thing pops up, it's either misusing the object (shouldn't be shared), or the object is missing a shared method. The error is really awful. After finding this case, I spotted a few others. This error message is extremely generic and used in many other cases. In more mature areas of the code, the compiler issues a much more helpful message on the very next line. For shared, there's no specialized error message and it leaves the user scratching their head...
 Can anyone point me to a decent
 documentation of how "shared" works? I have read chapter 13 of The D
 Programming Language and it is not sufficient for the level of
 understanding I seek.
Nope. D is notorious for having no specs or other documentation to give a detailed understanding. I would have assumed TDPL was the best place. (I don't have a copy)
 That is a lot of question. Hopefully I get answer to at least one.
Mar 30 2011
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
TLS takes some time to getting used to. Doing multithreading in a way
forces me to stop using globals, because I always get bitten when
spawning new threads and only later realizing that my globals have
been re-initialized to their .init value. The new thread ends up
reading mostly zero-initialized values. And that of course leaves me
scratching my head when my code does something unexpected.

But I like the idea of having each thread do its own job. A thread for
the GUI, a thread for some special input devices, a background
high-priority thread that does heavy processing on some prealocated
data, and maybe a logging thread for debug builds. That's what I'm
aiming for at the moment, anyway.
Mar 30 2011
prev sibling parent reply Jose Armando Garcia <jsancio gmail.com> writes:
On Wed, Mar 30, 2011 at 9:39 PM, Jason House
<jason.james.house gmail.com> wrote:
 Jose Armando Garcia Wrote:

 Why am I getting this error? I suspect that synchronized is the
 problem.
A synchronized class is implicitly shared and most of the methods are syn=
chronized. =A0I say most because at a minimum, the constructor isn't synchr= onized on anything. =A0As you probably know shared is transitive, so all me= mbers are implicitly shared as well.
 How do I get around this error?
That's not easy to answer... =A0To get the compiler to shut up, you can c=
opy and paste FILE's destructor and mark it as shared. =A0Of course, every = method call to your file will similarly required shared methods. =A0If you = make no copies of the file object, and all accesses are from within your sy= nchronized methods, you can probably cast away shared while making the meth= od calls. =A0Of course, the common theme here is that you're verifying the = multi-threaded safety of all this stuff along the way. =A0If you're not com= fortable doing that, then you probably want to do another design that you c= an prove works.

This is a great suggestion and that is what I do in my implementation
of the synchronized class but I can't cast away the call to the dtor.
That call is done by the compiler. I am going to look into __gshared.

 Does this mean that
 synchronized classes are not allowed to have as member
 unsynchronized/regular classes?
As I said above, shared is transitive. =A0It's implicit that all members =
are shared even though you don't mark them as such. =A0No shared objects ca= n have non-shared members. =A0If there are parts that are not accessed by m= ore than one thread, you can either restructure your code a bit, or make li= beral use of casts.
 Has anyone tried to write a
 multithreaded application using D?
Yes, and even succeeded :)
Which? And it it cannot be named what does it do? How many lines of code?
 Why is the error showing up in
 std/stdio.d and not in my file?
It's an awful error message. =A0I complained about it back in 2009: http:=
//d.puremagic.com/issues/show_bug.cgi?id=3D3642
 When this kind of thing pops up, it's either misusing the object (shouldn=
't be shared), or the object is missing a shared method. =A0The error is re= ally awful. =A0After finding this case, I spotted a few others. =A0This err= or message is extremely generic and used in many other cases. =A0In more ma= ture areas of the code, the compiler issues a much more helpful message on = the very next line. =A0For shared, there's no specialized error message and= it leaves the user scratching their head...
 Can anyone point me to a decent
 documentation of how "shared" works? I have read chapter 13 of The D
 Programming Language and it is not sufficient for the level of
 understanding I seek.
Nope. =A0D is notorious for having no specs or other documentation to giv=
e a detailed understanding. =A0I would have assumed TDPL was the best place= . =A0(I don't have a copy)
 That is a lot of question. Hopefully I get answer to at least one.
Mar 31 2011
parent reply Jason House <jason.james.house gmail.com> writes:
Jose Armando Garcia Wrote:

 On Wed, Mar 30, 2011 at 9:39 PM, Jason House
 <jason.james.house gmail.com> wrote:
 Jose Armando Garcia Wrote:

 How do I get around this error?
That's not easy to answer...  To get the compiler to shut up, you can copy and paste FILE's destructor and mark it as shared.  Of course, every method call to your file will similarly required shared methods.  If you make no copies of the file object, and all accesses are from within your synchronized methods, you can probably cast away shared while making the method calls.  Of course, the common theme here is that you're verifying the multi-threaded safety of all this stuff along the way.  If you're not comfortable doing that, then you probably want to do another design that you can prove works.
This is a great suggestion and that is what I do in my implementation of the synchronized class but I can't cast away the call to the dtor. That call is done by the compiler. I am going to look into __gshared.
For one, definitely file a bug report! You might be able to mark your FILE as __gshared or make it a pointer. As a pointer, you manage the lifetime, and can cast away shared before calling delete, clear, or whatever. If file is using TLS globals, or is otherwise unsafe to use the way you want, then you need messages passing.
 Has anyone tried to write a
 multithreaded application using D?
Yes, and even succeeded :)
Which? And it it cannot be named what does it do? How many lines of code?
It was an open source hobby project called housebot. I don't have the LOC handy, but it is a program to play the game of go. It has a shared search tree and a hash tree filled with weak pointers. Control messages are done through message passing. Message passing did not exist in Phobos when I wrote it, and I had to take atomic increment code from Tango.
Mar 31 2011
parent Jose Armando Garcia <jsancio gmail.com> writes:
On Thu, Mar 31, 2011 at 7:59 PM, Jason House
<jason.james.house gmail.com> wrote:
 Jose Armando Garcia Wrote:

 On Wed, Mar 30, 2011 at 9:39 PM, Jason House
 <jason.james.house gmail.com> wrote:
 Jose Armando Garcia Wrote:

 How do I get around this error?
That's not easy to answer... =A0To get the compiler to shut up, you ca=
n copy and paste FILE's destructor and mark it as shared. =A0Of course, eve= ry method call to your file will similarly required shared methods. =A0If y= ou make no copies of the file object, and all accesses are from within your= synchronized methods, you can probably cast away shared while making the m= ethod calls. =A0Of course, the common theme here is that you're verifying t= he multi-threaded safety of all this stuff along the way. =A0If you're not = comfortable doing that, then you probably want to do another design that yo= u can prove works.

 This is a great suggestion and that is what I do in my implementation
 of the synchronized class but I can't cast away the call to the dtor.
 That call is done by the compiler. I am going to look into __gshared.
For one, definitely file a bug report! You might be able to mark your FILE as __gshared or make it a pointer. As=
a pointer, you manage the lifetime, and can cast away shared before callin= g delete, clear, or whatever.
 If file is using TLS globals, or is otherwise unsafe to use the way you w=
ant, then you need messages passing.

I'll file a bug report when I get back to my computer and I can verify
that my memory is not failing me.

 Has anyone tried to write a
 multithreaded application using D?
Yes, and even succeeded :)
Which? And it it cannot be named what does it do? How many lines of code=
?

 It was an open source hobby project called housebot. I don't have the LOC=
handy, but it is a program to play the game of go. It has a shared search = tree and a hash tree filled with weak pointers. Control messages are done t= hrough message passing. Message passing did not exist in Phobos when I wrot= e it, and I had to take atomic increment code from Tango.

Thanks!
Mar 31 2011