Jump to page: 1 24  
Page
Thread overview
Any chance to avoid monitor field in my class?
May 07, 2014
Yuriy
May 07, 2014
bearophile
May 07, 2014
Rene Zwanenburg
May 08, 2014
Yuriy
May 08, 2014
Yuriy
May 08, 2014
Yuriy
May 08, 2014
Yuriy
May 08, 2014
bearophile
May 08, 2014
Yuriy
May 09, 2014
bearophile
May 09, 2014
Yuriy
May 09, 2014
flamencofantasy
May 09, 2014
John Colvin
May 09, 2014
Yuriy
May 13, 2014
Yuriy
May 08, 2014
Yuriy
May 08, 2014
John Colvin
May 13, 2014
Daniel Murphy
May 13, 2014
Yuriy
May 14, 2014
Daniel Murphy
May 14, 2014
Yuriy
May 15, 2014
Daniel Murphy
May 15, 2014
Yuriy
May 16, 2014
Daniel Murphy
May 14, 2014
Dejan Lekic
May 14, 2014
Yuriy
May 14, 2014
Ali Çehreli
May 14, 2014
Yuriy
May 07, 2014
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 08, 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.
>
> -Steve

Yes, 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:
>> 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
>
> Yes, 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).

To what end? What are you trying to save?

> 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:
>> 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.

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).

>> 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.

Then what is this object? All D objects derive from Object.

>> 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?

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!

-Steve
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?? =)

>>> It would not be derived from Object, which has the field. In other words, this would crash:
Those are your words.

> 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:

>> 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,

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.

> 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.

>
>>>> It would not be derived from Object, which has the field. In other words, this would crash:
> Those are your words.

I'm assuming you want D classes, but without the monitor object. D classes derive from Object.

>
>> Then what is this object? All D objects derive from Object.
> Those are your words also =)

"Any chance to avoid monitor field in my class?" Those are your words. What is it that you want?

>> 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?

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.

>> 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?
> }

shared != thread safe. You still need to synchronize

-Steve
« First   ‹ Prev
1 2 3 4