digitalmars.D.learn - Any chance to avoid monitor field in my class?
- Yuriy (3/3) May 07 2014 Hello, is there a way of reducing size of an empty class to just
- bearophile (5/8) May 07 2014 extern(C++) classes is only for interfacing with C++ code. It's
- Rene Zwanenburg (3/6) May 07 2014 May I ask what your use case is? Perhaps there's another solution
- Steven Schveighoffer (6/9) May 08 2014 The de-facto minimum size of a class is 16 bytes, due to the minimum blo...
- Yuriy (11/16) May 08 2014 Yes, but still the question remains open for non-empty classes
- Steven Schveighoffer (11/28) May 08 2014 It would not be derived from Object, which has the field. In other words...
- Yuriy (14/21) May 08 2014 I'm trying to reimplement std.variant in a nice OOP way, that
- Steven Schveighoffer (14/34) May 08 2014 Well, I don't think I know enough to judge whether what you are doing is...
- Yuriy (30/44) May 08 2014 Hm.. Stack/emplace, arrays, n-dimensional arrays? :) Besides, if
- Steven Schveighoffer (16/60) May 08 2014 How many of these? In order to justify saving 8 bytes per instance, you ...
- Yuriy (13/24) May 08 2014 Or again you can emplace them in the heap, so that they occupy a
- bearophile (5/6) May 08 2014 Also take a look at the Rust language, that avoids some of your
- Yuriy (3/5) May 08 2014 Done already =). Rust is great, but I like D, and i strongly
- bearophile (4/5) May 09 2014 Oh, good. Do you want to briefly explain why? :)
- Yuriy (14/14) May 09 2014 Imho, offtop, also i'm a C++/Obj-C guy and that might partially
- flamencofantasy (4/4) May 09 2014 One thing I hate about C# (which is what I use professionally) is
- John Colvin (4/10) May 09 2014 If it can be changed without breaking existing code, you might be
- Yuriy (1/1) May 09 2014 flamencofantasy, thanx for that! Where do we vote here? =)
- Yuriy (2/2) May 13 2014 Moving further discussion to here:
- Steven Schveighoffer (16/37) May 08 2014 I'm not, I'm trying to help you justify the path your taking :) Because ...
- Yuriy (16/20) May 08 2014 I want to provide it, but before i do, i want to know if there
- John Colvin (5/8) May 08 2014 Just a general FYI:
- Daniel Murphy (2/5) May 13 2014 What exactly is the mangling problem with extern(C++) classes?
- Yuriy (7/8) May 13 2014 Can't use D arrays (and strings) as function argument types.
- Daniel Murphy (3/11) May 14 2014 I'm not getting any errors with the development head. What
- Yuriy (8/10) May 14 2014 Hm, now that's strange. Building with latest public version seems
- Daniel Murphy (20/25) May 15 2014 Never mind I can reproduce the bug with master, I probably ran 'dmd test...
- Yuriy (4/7) May 15 2014 Ok, i can understand that, but what about this one:
- Daniel Murphy (21/24) May 16 2014 Similar problem, D arrays cannot be mangled correctly with C++ mangling.
- Dejan Lekic (3/11) May 14 2014 that should not compile at all. Perhaps you thought extern(C++)
- Yuriy (4/6) May 14 2014 Ok, how about this one?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (23/29) May 14 2014 extern(C++) interface I
- Yuriy (10/14) May 14 2014 Ali, i think that paragraph is talking about another case, which
Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.
May 07 2014
Yuriy:Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.extern(C++) classes is only for interfacing with C++ code. It's not to write regular D code. Bye, bearophile
May 07 2014
On Wednesday, 7 May 2014 at 14:44:57 UTC, Yuriy wrote:Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.May I ask what your use case is? Perhaps there's another solution to the problem.
May 07 2014
On Wed, 07 May 2014 10:44:55 -0400, Yuriy <yuriy.glukhov gmail.com> wrote:Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.The de-facto minimum size of a class is 16 bytes, due to the minimum block size of the heap. 8 bytes vtbl pointer on 64-bit systems would still allocate into 16-byte blocks. -Steve
May 08 2014
On Thursday, 8 May 2014 at 14:57:37 UTC, Steven Schveighoffer wrote:The de-facto minimum size of a class is 16 bytes, due to the minimum block size of the heap. 8 bytes vtbl pointer on 64-bit systems would still allocate into 16-byte blocks. -SteveYes, but still the question remains open for non-empty classes (e.g. want to use a 64bit useful payload), and for _emplacing_ any classes anywhere (e.g. on stack). Afaiu, there's no solution except for declaring extern(C++) (yes, i know, it's a hack), and it will not work, if a class is templated on something which can not be cpp-mangled. So the question is: is there any reason why this is not possible? I mean, maybe this question was closed long before. Also, do shared classes actually require monitors?
May 08 2014
On Thu, 08 May 2014 13:21:07 -0400, Yuriy <yuriy.glukhov gmail.com> wrote:On Thursday, 8 May 2014 at 14:57:37 UTC, Steven Schveighoffer wrote:To what end? What are you trying to save?The de-facto minimum size of a class is 16 bytes, due to the minimum block size of the heap. 8 bytes vtbl pointer on 64-bit systems would still allocate into 16-byte blocks. -SteveYes, but still the question remains open for non-empty classes (e.g. want to use a 64bit useful payload), and for _emplacing_ any classes anywhere (e.g. on stack).Afaiu, there's no solution except for declaring extern(C++) (yes, i know, it's a hack), and it will not work, if a class is templated on something which can not be cpp-mangled. So the question is: is there any reason why this is not possible? I mean, maybe this question was closed long before.It would not be derived from Object, which has the field. In other words, this would crash: synchronized(cast(Object)obj) { ... }Also, do shared classes actually require monitors?Perhaps you meant unshared classes? No, they don't, but a monitor is only allocated on demand, so you don't have to worry about it. However, note that it is perfectly acceptable to cast to and from shared as long as you guarantee the uniqueness of the reference. If the monitor is not present, this can cause problems. -Steve
May 08 2014
On Thursday, 8 May 2014 at 17:49:01 UTC, Steven Schveighoffer wrote:To what end? What are you trying to save?I'm trying to reimplement std.variant in a nice OOP way, that supports CTFE, zero-size and a minimal amount of void*-casts. For that i'm using my VariantPayload(T) class, which i want to be as small as possible, as this is supposed to be an utility class which you never know how will be used.It would not be derived from Object, which has the field. In other words, this would crash: synchronized(cast(Object)obj) { ... }Wouldn't cast(Object) return null here, so that synchronized will throw or assert or smth? I see no reason for a crash.Perhaps you meant unshared classes? No, they don't, but a monitor is only allocated on demand, so you don't have to worry about it.Errm.. I'm not sure i understand the subject correctly, but according to Alexandrescu's book, a class declared as shared does not require synchronized() over it. I mean, it manages it's synchronization inside itself, and it's user just has to trust it. And if so, why ever synchronizing() on it?
May 08 2014
On Thu, 08 May 2014 14:17:42 -0400, Yuriy <yuriy.glukhov gmail.com> wrote:On Thursday, 8 May 2014 at 17:49:01 UTC, Steven Schveighoffer wrote:Well, I don't think I know enough to judge whether what you are doing is worthwhile... But my question more was about where do you plan to put so many of these objects that you will save a significant amount of bytes, aside from the heap (which already uses 16-byte blocks).To what end? What are you trying to save?I'm trying to reimplement std.variant in a nice OOP way, that supports CTFE, zero-size and a minimal amount of void*-casts. For that i'm using my VariantPayload(T) class, which i want to be as small as possible, as this is supposed to be an utility class which you never know how will be used.Then what is this object? All D objects derive from Object.It would not be derived from Object, which has the field. In other words, this would crash: synchronized(cast(Object)obj) { ... }Wouldn't cast(Object) return null here, so that synchronized will throw or assert or smth? I see no reason for a crash.The meaning of shared is not well defined. Even TDPL is outdated on this. The idea in the book is that shared types would use memory barriers to ensure correct ordering of access, and correct data access. But it does not prevent races for multiple threads, you still need synchronized. Unshared objects, on the other hand, should not ever need synchronization tools, since only one thread has access! -StevePerhaps you meant unshared classes? No, they don't, but a monitor is only allocated on demand, so you don't have to worry about it.Errm.. I'm not sure i understand the subject correctly, but according to Alexandrescu's book, a class declared as shared does not require synchronized() over it. I mean, it manages it's synchronization inside itself, and it's user just has to trust it. And if so, why ever synchronizing() on it?
May 08 2014
But my question more was about where do you plan to put so many of these objects that you will save a significant amount of bytes, aside from the heap (which already uses 16-byte blocks).Hm.. Stack/emplace, arrays, n-dimensional arrays? :) Besides, if we're talking of D as a system language to replace C++ and to scratch everything out of a silicon wafer (also think of embedded platforms here), it's crucial for me to be able to control such things. From my experience, in a 5000-class project you would have about 20 classes that need to be synchronized on. Moreover, mutex synchronization is not in fashion nowadays, as we tend to use transitional synchronization. And so my 4980 classes will contain an extra field i don't use. What?? =)Those are your words.It would not be derived from Object, which has the field. In other words, this would crash:Then what is this object? All D objects derive from Object.Those are your words also =)The meaning of shared is not well defined. Even TDPL is outdated on this. The idea in the book is that shared types would use memory barriers to ensure correct ordering of access, and correct data access. But it does not prevent races for multiple threads, you still need synchronized.Yes, i understand that. By implementing a shared class, you're on your own with syncing, but also you tell the user, that your class doesn't need to be synchronized on. Right?Unshared objects, on the other hand, should not ever need synchronization tools, since only one thread has access!Here's two use-cases. class A {} shared class B {} // Somewhere in code { shared A sharedA; // This would need synchronized() on access. A unsharedA; // This would not. But since, the class is defined as unshared, we still will have __monitor in it, and that is good, since we can cast between unshared A and shared A. B b; shared B sharedB; // Here in both cases we know, that we will never need to sync on b or sharedB, as both of those are "thread safe" (it's not our business, how they do it, but they kinda are). So do we need this __monitor, which will never be used actually? }
May 08 2014
On Thu, 08 May 2014 15:47:46 -0400, Yuriy <yuriy.glukhov gmail.com> wrote:How many of these? In order to justify saving 8 bytes per instance, you have have a lot. I don't see emplacing thousands or tens of thousands of objects on the stack.But my question more was about where do you plan to put so many of these objects that you will save a significant amount of bytes, aside from the heap (which already uses 16-byte blocks).Hm.. Stack/emplace,arrays, n-dimensional arrays?Arrays of objects are stored as arrays of object references, with each one pointing at a separate block on the heap.:) Besides, if we're talking of D as a system language to replace C++ and to scratch everything out of a silicon wafer (also think of embedded platforms here), it's crucial for me to be able to control such things. From my experience, in a 5000-class project you would have about 20 classes that need to be synchronized on. Moreover, mutex synchronization is not in fashion nowadays, as we tend to use transitional synchronization. And so my 4980 classes will contain an extra field i don't use. What?? =)In D, class is not used for such things, struct is.I'm assuming you want D classes, but without the monitor object. D classes derive from Object.Those are your words.It would not be derived from Object, which has the field. In other words, this would crash:"Any chance to avoid monitor field in my class?" Those are your words. What is it that you want?Then what is this object? All D objects derive from Object.Those are your words also =)A defined shared class I think is supposed to imply that all its methods are shared (meaning the 'this' pointer must be shared). It does not imply that they are thread safe.The meaning of shared is not well defined. Even TDPL is outdated on this. The idea in the book is that shared types would use memory barriers to ensure correct ordering of access, and correct data access. But it does not prevent races for multiple threads, you still need synchronized.Yes, i understand that. By implementing a shared class, you're on your own with syncing, but also you tell the user, that your class doesn't need to be synchronized on. Right?shared != thread safe. You still need to synchronize -SteveUnshared objects, on the other hand, should not ever need synchronization tools, since only one thread has access!Here's two use-cases. class A {} shared class B {} // Somewhere in code { shared A sharedA; // This would need synchronized() on access. A unsharedA; // This would not. But since, the class is defined as unshared, we still will have __monitor in it, and that is good, since we can cast between unshared A and shared A. B b; shared B sharedB; // Here in both cases we know, that we will never need to sync on b or sharedB, as both of those are "thread safe" (it's not our business, how they do it, but they kinda are). So do we need this __monitor, which will never be used actually? }
May 08 2014
How many of these? In order to justify saving 8 bytes per instance, you have have a lot. I don't see emplacing thousands or tens of thousands of objects on the stack.Ok, i guess i have to agree with you. But. Why are you protecting __monitors so eagerly? :)Arrays of objects are stored as arrays of object references, with each one pointing at a separate block on the heap.Or again you can emplace them in the heap, so that they occupy a continuous chunk.In D, class is not used for such things, struct is.But classes have vtbls which is an ultimate feature for me, and moreover, it works in ctfe, while "reinventing" vtbls for ctfe might be a challenging task.I'm assuming you want D classes, but without the monitor object. D classes derive from Object. "Any chance to avoid monitor field in my class?" Those are your words. What is it that you want?Thats right. I was saying that extern(C++) almost suits me except for it's mangling. And you said that extern(C++) classes are not derived from Object? But still such objects would have RTTI which will forbid casting to Object, wouldn't they?shared != thread safe. You still need to synchronizeOk. So shared class is not a reason to omit __monitor field, as it still can be used, am i right here?
May 08 2014
Yuriy:But. Why are you protecting __monitors so eagerly? :)Also take a look at the Rust language, that avoids some of your problems :-) Bye, bearophile
May 08 2014
Also take a look at the Rust language, that avoids some of your problems :-)Done already =). Rust is great, but I like D, and i strongly believe it's the next big language. If only it could allow a bit more tweaks ;)
May 08 2014
Yuriy:but I like D, and i strongly believe it's the next big language.Oh, good. Do you want to briefly explain why? :) Bye, bearophile
May 09 2014
Imho, offtop, also i'm a C++/Obj-C guy and that might partially explain my preferences, but here are some more reasons: 1. I like the concept of CT-reflection and CTFE a lot. This makes metaprogramming extremely powerful without any RT overheads. It brings a lot more control to what goes to RT. I guess D still needs to shrink it's runtime a bit more, and __monitors is just another example of that. switch to D without loosing any bit of their productivity, but gaining lots of possibilities, that can be used in future. And developers should think of D one day =). 3. That's the most arguable, but D's syntax and semantics looks much cleaner and uniform to me than Rust's.
May 09 2014
the sync block index in every single class instance. Why not have the developer decide when he needs a Monitor and manually use it?! I am disappointed D took the same route.
May 09 2014
On Friday, 9 May 2014 at 14:56:21 UTC, flamencofantasy wrote:is the sync block index in every single class instance. Why not have the developer decide when he needs a Monitor and manually use it?! I am disappointed D took the same route.If it can be changed without breaking existing code, you might be able to convince people to make it somehow optional or elided when unnecessary.
May 09 2014
flamencofantasy, thanx for that! Where do we vote here? =)
May 09 2014
Moving further discussion to here: http://forum.dlang.org/thread/xpliectmvwrwthamquke forum.dlang.org
May 13 2014
On Thu, 08 May 2014 17:05:56 -0400, Yuriy <yuriy.glukhov gmail.com> wrote:I'm not, I'm trying to help you justify the path your taking :) Because where it's currently leading is somewhere that D doesn't support. This means in order to support it, you have to maintain a parallel compiler, or somehow convince the compiler writers to add such support. Neither of these burdens is small.How many of these? In order to justify saving 8 bytes per instance, you have have a lot. I don't see emplacing thousands or tens of thousands of objects on the stack.Ok, i guess i have to agree with you. But. Why are you protecting __monitors so eagerly? :)This is not a good idea. The dtors of classes in the GC is stored per block, not per chunk of a block.Arrays of objects are stored as arrays of object references, with each one pointing at a separate block on the heap.Or again you can emplace them in the heap, so that they occupy a continuous chunk.Removing the monitor could also prove quite challenging. I don't doubt your reasons, but then again, you have what you have right now in D. Asking for more, you have to provide it, or convince others to. If it's the latter, you need to make a very very strong case.In D, class is not used for such things, struct is.But classes have vtbls which is an ultimate feature for me, and moreover, it works in ctfe, while "reinventing" vtbls for ctfe might be a challenging task.extern(C++) objects are not considered D objects. A D object can implement a C++ interface, but once you get to the C++ interface, you cannot go back. This sounds to me very different from your goal. -SteveI'm assuming you want D classes, but without the monitor object. D classes derive from Object. "Any chance to avoid monitor field in my class?" Those are your words. What is it that you want?Thats right. I was saying that extern(C++) almost suits me except for it's mangling. And you said that extern(C++) classes are not derived from Object? But still such objects would have RTTI which will forbid casting to Object, wouldn't they?
May 08 2014
I don't doubt your reasons, but then again, you have what you have right now in D. Asking for more, you have to provide it, or convince others to. If it's the latter, you need to make a very very strong case.I want to provide it, but before i do, i want to know if there were any decisions made earlier, that would render my work useless. I mean, i have to know all possible cons for not having __monitor in an instance. What i suggest is the following: - Object does not have any __monitor field by default. - One can add a __monitor object to his class. - Offset to monitor is stored in TypeInfo. -1 if doesn't exist. - synchronized() inspects typeInfo. If an object has monitor, then it is used. Otherwise, the monitor is allocated/looked up in a global hash-table from object pointer to monitor. This way we could achieve performance in terms of both speed and memory. Also old code would not break. Some additional optimizations might always include a __monitor field to a class, if compiler can prove, that this class is being synchronized on.
May 08 2014
On Wednesday, 7 May 2014 at 14:44:57 UTC, Yuriy wrote:Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.Just a general FYI: Classes are relatively heavyweight in D. struct-based approaches are often favoured, as can be seen across the more heavily developed parts of phobos.
May 08 2014
"Yuriy" wrote in message news:uflaemdlxvavfmvkbudq forum.dlang.org...Hello, is there a way of reducing size of an empty class to just vtbl? I tried to declare it as extern(C++) which works, but has a nasty side effect of limited mangling.What exactly is the mangling problem with extern(C++) classes?
May 13 2014
On Tuesday, 13 May 2014 at 17:09:01 UTC, Daniel Murphy wrote:What exactly is the mangling problem with extern(C++) classes?Can't use D arrays (and strings) as function argument types. Can't use D array types as template arguments. extern (C++) MyClass(T) { } MyClass!string a; // Mangling error
May 13 2014
On Tuesday, 13 May 2014 at 17:41:42 UTC, Yuriy wrote:On Tuesday, 13 May 2014 at 17:09:01 UTC, Daniel Murphy wrote:I'm not getting any errors with the development head. What os/compiler version?What exactly is the mangling problem with extern(C++) classes?Can't use D arrays (and strings) as function argument types. Can't use D array types as template arguments. extern (C++) MyClass(T) { } MyClass!string a; // Mangling error
May 14 2014
On Wednesday, 14 May 2014 at 08:47:38 UTC, Daniel Murphy wrote:I'm not getting any errors with the development head. What os/compiler version?Hm, now that's strange. Building with latest public version seems to work. However, development head is doing the following: $ ./test.d Error: ICE: Unsupported type string Assertion failed: (0), function visit, file cppmangle.c, line 440. I'm using MacOS 10.9.2. The test.d is: http://dpaste.dzfl.pl/2aa4ca932be1
May 14 2014
"Yuriy" wrote in message news:rfirqtgbparjbqxwtppo forum.dlang.org...On Wednesday, 14 May 2014 at 08:47:38 UTC, Daniel Murphy wrote:Never mind I can reproduce the bug with master, I probably ran 'dmd test.d' instead of './dmd test.d' after building dmd. This version seems to compile - the new manger can't handle extern(C++) functions with D arrays as arguments or return types. extern(C++) class A(T) { extern(D): string hi() { return "asdf"; } } void main() { A!string a; } Only the subset of extern(C++) required to interface with actual C++ code has been tested at all, so using it with D-only types is going to be fairly unpleasant.I'm not getting any errors with the development head. What os/compiler version?Hm, now that's strange. Building with latest public version seems to work. However, development head is doing the following:
May 15 2014
On Thursday, 15 May 2014 at 11:51:38 UTC, Daniel Murphy wrote:This version seems to compile - the new manger can't handle extern(C++) functions with D arrays as arguments or return types.Ok, i can understand that, but what about this one: http://dpaste.dzfl.pl/6a9961e32e6d It doesn't use d arrays in function interfaces. Should it work?
May 15 2014
"Yuriy" wrote in message news:klosrzuxwmvilupzzuvm forum.dlang.org...Ok, i can understand that, but what about this one: http://dpaste.dzfl.pl/6a9961e32e6d It doesn't use d arrays in function interfaces. Should it work?Similar problem, D arrays cannot be mangled correctly with C++ mangling. This compiles: extern(C++) interface I { extern(D): int hi(); } extern(C++) class A(T) : I { extern(D): override int hi() { return 0; } } void main() { A!string a; }
May 16 2014
On Tuesday, 13 May 2014 at 17:41:42 UTC, Yuriy wrote:On Tuesday, 13 May 2014 at 17:09:01 UTC, Daniel Murphy wrote:that should not compile at all. Perhaps you thought extern(C++) interface MyClass(T) ?What exactly is the mangling problem with extern(C++) classes?Can't use D arrays (and strings) as function argument types. Can't use D array types as template arguments. extern (C++) MyClass(T) { } MyClass!string a; // Mangling error
May 14 2014
On Wednesday, 14 May 2014 at 10:21:00 UTC, Dejan Lekic wrote:that should not compile at all. Perhaps you thought extern(C++) interface MyClass(T) ?Ok, how about this one? http://dpaste.dzfl.pl/04655ff6ddfd It doesn't compile either.
May 14 2014
On 05/14/2014 04:15 AM, Yuriy wrote:On Wednesday, 14 May 2014 at 10:21:00 UTC, Dejan Lekic wrote:extern(C++) interface I { string hi(); } extern(C++) class A(T) : I { override string hi() { return "asdf"; } } void main() { A!string a; } /d208/f532.d(9): Error: class f532.A!(string).A cannot create C++ classes /d208/f532.d(19): Error: template instance f532.A!(string) error instantiating Yeah, that is a documented limitation when using C++ code. C++ templates cannot be used in D. "C++ Templates" here: http://dlang.org/cpp_interface.html Alithat should not compile at all. Perhaps you thought extern(C++) interface MyClass(T) ?Ok, how about this one? http://dpaste.dzfl.pl/04655ff6ddfd It doesn't compile either.
May 14 2014
Ali, i think that paragraph is talking about another case, which is not my case. I'm not trying to use C++ templates, nor to export a D template to C++. Besides, i guess that D template, implementing a C++ interface is perfectly valid, regardless it's template arguments, since it is instantiated on the D side anyway. Also i guess that such types as D arrays should not support mangling when used as function arguments/rettype, they are not compatible with C++ anyway, but when they become part of a class template, they should mangle somehow. IMHO. On Wednesday, 14 May 2014 at 14:08:52 UTC, Ali Çehreli wrote:Yeah, that is a documented limitation when using C++ code. C++ templates cannot be used in D. "C++ Templates" here: http://dlang.org/cpp_interface.html Ali
May 14 2014