www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Get a Reference to an Object's Monitor

reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
Is there any way to get a reference to an object's monitor? This would
be very useful because a Condition has to be tied to a Mutex, and
since objects already have a reference to a Mutex built in, it doesn't
make much sense to create another (and add another reference to the
class) when the end effect is the same.

Example:
---
class Example {
private:
    Mutex _lock;
    Condition _condition;
public
    this() {
        _lock = new Mutex();
        _condition = new Condition(_lock);
    }
    void methodA() shared {
        synchronized(_lock) {
            // do some stuff
            while(someTest)
                _condition.wait();
        }
    }
    void methodB() shared {
        synchronized(_lock) {
            //do some stuff
            _condition.notifyAll();
        }
    }
}
---

If I could get a reference to Example's monitor, this example becomes:

---
synchronized class Example {
private:
    Condition _condition;
public
    this() {
        _condition = new Condition(this.__monitor);
    }
    void methodA() {
        // do some stuff
        while(someTest)
            _condition.wait();
    }
    void methodB() {
        //do some stuff
        _condition.notifyAll();
    }
}
---

Which is much more fool-proof to write.
Dec 20 2011
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Andrew Wiley:

 Is there any way to get a reference to an object's monitor?

Is this useful? From the D2 docs:
 The properties .__vptr and .__monitor give access to the class object's vtbl[]
and
 monitor, respectively, but should not be used in user code.

Bye, bearophile
Dec 20 2011
prev sibling next sibling parent reply Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Tue, Dec 20, 2011 at 2:29 PM, bearophile <bearophileHUGS lycos.com> wrote:
 Andrew Wiley:

 Is there any way to get a reference to an object's monitor?

Is this useful? From the D2 docs:
 The properties .__vptr and .__monitor give access to the class object's vtbl[]
and
 monitor, respectively, but should not be used in user code.


I've seen that, but using the built-in monitor explicitly in a few places means it's much harder to make mistakes like locking the wrong lock or forgetting to lock altogether. In my two code examples, the first one is much easier to screw up as the class gets larger and larger because marking methods as "shared" eliminates any guarantees the compiler can provide. I suspect the reason they advise not using it in user code is that the monitor is lazily initialized (if I remember correctly), so I'd have to initialize it myself.
Dec 20 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Andrew Wiley:

 I suspect the reason they advise not using it in user code is that the
 monitor is lazily initialized (if I remember correctly), so I'd have
 to initialize it myself.

I see. I have a question myself. Regarding this, do you know why __vptr is an instance attribute instead of a class attribute? http://d.puremagic.com/issues/show_bug.cgi?id=3939 Bye, bearophile
Dec 20 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/21/2011 12:40 AM, bearophile wrote:
 Andrew Wiley:

 I suspect the reason they advise not using it in user code is that the
 monitor is lazily initialized (if I remember correctly), so I'd have
 to initialize it myself.

I see. I have a question myself. Regarding this, do you know why __vptr is an instance attribute instead of a class attribute? http://d.puremagic.com/issues/show_bug.cgi?id=3939 Bye, bearophile

The vptr is used to implement dynamic method calls. Therefore it might not correspond to the static type of the reference and has to be an instance attribute. Why would you have to manipulate vptr? You can use typeid to compare instances for identity of their corresponding type. Anyway, to get the vptr of a class C, do this: void** vptr = typeid(C).vtbl.ptr;
Dec 20 2011
parent reply bearophile <bearophileHUGS lycos.com> writes:
Timon Gehr:

 The vptr is used to implement dynamic method calls.
 Therefore it might not correspond to the static type of
 the reference and has to be an instance attribute.

Right. In that old enhancement request I was asking for __vptr to be both a class attribute and instance attribute.
 Why would you have to manipulate vptr?

To quickly know what's the class of a class instance that's on the heap, to avoid structs because I sometimes need virtual methods, and avoid initializing another field just for this purpose. It's for a special usage.
 You can use typeid to compare 
 instances for identity of their corresponding type.

I think I need something more light.
 Anyway, to get the vptr of a class C, do this:
 
 void** vptr = typeid(C).vtbl.ptr;

I will compare this to the solution I have used to safe. Creating a class instance of TypeInfo just to know the value of what it looks like a static field (the head of the virtual table) seems strange. Bye, bearophile
Dec 20 2011
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 12/21/2011 01:27 AM, bearophile wrote:
 Timon Gehr:

 The vptr is used to implement dynamic method calls.
 Therefore it might not correspond to the static type of
 the reference and has to be an instance attribute.

Right. In that old enhancement request I was asking for __vptr to be both a class attribute and instance attribute.

__vptr is not even a documented feature, so your request seems strange to me.
 Why would you have to manipulate vptr?

To quickly know what's the class of a class instance that's on the heap, to avoid structs because I sometimes need virtual methods, and avoid initializing another field just for this purpose. It's for a special usage.
 You can use typeid to compare
 instances for identity of their corresponding type.

I think I need something more light.

class A{} class B: A{} void main(){ A a = new B; assert(typeid(a) is typeid(B)); }
 Anyway, to get the vptr of a class C, do this:

 void** vptr = typeid(C).vtbl.ptr;

I will compare this to the solution I have used to safe. Creating a class instance of TypeInfo just to know the value of what it looks like a static field (the head of the virtual table) seems strange.

compiler generated typeinfo that is in the static data section.
Dec 20 2011
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12/21/2011 02:03 AM, Timon Gehr wrote:
 __vptr is not even a documented feature, so your request seems strange
 to me.

Ok, seems it is in the docs.
Dec 20 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Tue, Dec 20, 2011 at 3:40 PM, bearophile <bearophileHUGS lycos.com> wrote:
 Andrew Wiley:

 I suspect the reason they advise not using it in user code is that the
 monitor is lazily initialized (if I remember correctly), so I'd have
 to initialize it myself.

I see.

It looks like Sean is ahead of me:
From core.sync.mutex:

this(Object o); Initializes a mutex object and sets it as the monitor for o. So my example would look like: --- synchronized class Example { private: Condition _condition; public this() { auto lock = new Mutex(this); _condition = new Condition(lock); } void methodA() { // do some stuff while(someTest) _condition.wait(); } void methodB() { //do some stuff _condition.notifyAll(); } } ---
Dec 20 2011
prev sibling next sibling parent Sean Kelly <sean invisibleduck.org> writes:
Yup.=20

Sent from my iPhone

On Dec 20, 2011, at 4:22 PM, Andrew Wiley <wiley.andrew.j gmail.com> wrote:

 On Tue, Dec 20, 2011 at 3:40 PM, bearophile <bearophileHUGS lycos.com> wro=

 Andrew Wiley:
=20
 I suspect the reason they advise not using it in user code is that the
 monitor is lazily initialized (if I remember correctly), so I'd have
 to initialize it myself.

I see.

It looks like Sean is ahead of me: =46rom core.sync.mutex: =20 this(Object o); Initializes a mutex object and sets it as the monitor for o. =20 So my example would look like: --- synchronized class Example { private: Condition _condition; public this() { auto lock =3D new Mutex(this); _condition =3D new Condition(lock); } void methodA() { // do some stuff while(someTest) _condition.wait(); } void methodB() { //do some stuff _condition.notifyAll(); } } ---

Dec 20 2011
prev sibling next sibling parent Andrew Wiley <wiley.andrew.j gmail.com> writes:
On Tue, Dec 20, 2011 at 9:16 PM, Sean Kelly <sean invisibleduck.org> wrote:
 Yup.

Do you have any plans to eliminate the fun things like (cast()condition).wait(); ? It seems like most of the classes in core.sync should be declared as shared classes. I realize there would be code breakage, but having to cast away shared everywhere I do anything beyond `synchronized` is pretty broken.
Dec 20 2011
prev sibling parent Sean Kelly <sean invisibleduck.org> writes:
I agree. I really need to fix this. 

Sent from my iPhone

On Dec 20, 2011, at 9:44 PM, Andrew Wiley <wiley.andrew.j gmail.com> wrote:

 On Tue, Dec 20, 2011 at 9:16 PM, Sean Kelly <sean invisibleduck.org> wrote:
 Yup.
 

Do you have any plans to eliminate the fun things like (cast()condition).wait(); ? It seems like most of the classes in core.sync should be declared as shared classes. I realize there would be code breakage, but having to cast away shared everywhere I do anything beyond `synchronized` is pretty broken.

Dec 20 2011