September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne Attachments: | Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Lionello Lunesu schrieb am 2006-09-29:
>> Thomas Kuehne wrote:
>>> Walter Bright schrieb am 2006-09-29:
>>>> The problem in general with hiding pointers is that it'll break with a moving garbage collector. You could work around this by 'pinning' the objects, but pinning objects long term is a bad idea.
>>> How about an GC allocation area that isn't searched for valid pointers but is still collected?
>> Couldn't we use malloc/free + RAII for that? ...auto_ptr<>?
>
> No. The trick is that this area is collected(and updated by a moving GC), but isn't considered while looking for pointers into the "normal" area.
I've been experimenting a bit and got up with the attached stuff.
I copy-pasted 'main' here to explain my point. SafePtr is a template class that wraps a pointer. It has custom (de)allocator using malloc/free, so it's not scanned by GC.
I create an object, Test, on the heap and have just one reference to it, the one on the stack. I also set the pointer in the SafePtr instance to that same object, but that occurence of the pointer is not scanned so doesn't count. When settings the reference to the object to null (and forcing a full collect cycle) the GC _will_ collect the object (eventhough we still had another reference to it in SafePtr).
As for the notification, the Test class keeps a list of pointers to IOnDelete, which it iterates in its destructor. SafePtr implements IOnDelete.OnDelete and resets its reference.
L.
void main()
{
auto SafePtr!(Test) x = new SafePtr!(Test);
Test test = new Test;
// Let the safe-pointer point to the test object
x.ptr = test;
// Now remove the (last) reference to the test object
test = null;
// We must do some operation here to get rid of any references on the stack
printf("%p\r",test); // overwrite stack
// Let the GC do a full collect (will collect the test object)
std.gc.fullCollect();
// The safe-pointer will have been notified
if (!x.ptr)
printf("Target was deleted by GC\n");
}
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | Thomas Kuehne wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Lionello Lunesu schrieb am 2006-09-29: >> Thomas Kuehne wrote: >>> Walter Bright schrieb am 2006-09-29: >>>> The problem in general with hiding pointers is that it'll break with a moving garbage collector. You could work around this by 'pinning' the objects, but pinning objects long term is a bad idea. >>> How about an GC allocation area that isn't searched for valid pointers >>> but is still collected? >> Couldn't we use malloc/free + RAII for that? ...auto_ptr<>? > > No. The trick is that this area is collected(and updated by a moving > GC), but isn't considered while looking for pointers into the "normal" > area. I think my other reply addresses the wrong issue, but I still think we can use RAII + c-heap. We just need 1 extra indirection: class Test { ~this() { printf("~Test\n"); } } class WeakPtr(T) { private T* _ptr; this() { _ptr = cast(T*)std.c.stdlib.malloc(_ptr.sizeof); } ~this() { printf("~WeakPtr\n"); std.c.stdlib.free(_ptr); } T ptr() { return *_ptr; } T ptr(T p) { return *_ptr = p; } } void main() { auto weak = new WeakPtr!(Object); auto object = new Test; weak.ptr = object; object = null; printf("%i\r",0);// do some stuff std.gc.fullCollect(); // collects object assert(weak.ptr !is null); weak = null; std.gc.fullCollect(); // collects weakptr } >dmd -debug -run weakref.d ~Test ~WeakPtr (not working in release; probably there's a ref left on the stack somewhere) L. |
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Thomas Kuehne | Thomas Kuehne wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Lionello Lunesu schrieb am 2006-09-29:
>> Thomas Kuehne wrote:
>>> Walter Bright schrieb am 2006-09-29:
>>>> The problem in general with hiding pointers is that it'll break with a moving garbage collector. You could work around this by 'pinning' the objects, but pinning objects long term is a bad idea.
>>> How about an GC allocation area that isn't searched for valid pointers
>>> but is still collected?
>> Couldn't we use malloc/free + RAII for that? ...auto_ptr<>?
>
> No. The trick is that this area is collected(and updated by a moving
> GC), but isn't considered while looking for pointers into the "normal"
> area.
Wait.. "and updated by a moving GC"... got it.. :S
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | Lionello Lunesu wrote:
> I think my other reply addresses the wrong issue, but I still think we can use RAII + c-heap. We just need 1 extra indirection:
>
> class Test {
> ~this() { printf("~Test\n"); }
> }
>
> class WeakPtr(T) {
> private T* _ptr;
> this() { _ptr = cast(T*)std.c.stdlib.malloc(_ptr.sizeof); }
> ~this() { printf("~WeakPtr\n"); std.c.stdlib.free(_ptr); }
> T ptr() { return *_ptr; }
> T ptr(T p) { return *_ptr = p; }
> }
But how can you tell if _ptr is valid or not? If you can't, it's pretty useless, as you can never safely dereference it...
xs0
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | On Fri, 29 Sep 2006 16:40:09 +0900, Bill Baxter wrote:
> I think railroading Qt's S&S into a language is the wrong approach. What goes into the language should be a more general mechanism on top of which schemes like dynamic S&S can be easily built.
Yeah, I was thinking this also the other day when talking about "hooks".
To be more concrete, I think it would be a great feature to allow
some of the hooking that modern debuggers do - e.g. from now on execute
this bit of code at entry or exit of a given function. In the context
of S&S as discussed in this thread, such functionality could allow
already written functions to start being used as either signals or slots
without requiring source code modifications to their definition. Signals
would be created by some library that hooks the end of the emitting
function and the GC issue could be solved by hooking the destruction of an
object (searching based on its address).
Undoubtably there would be many other cool options and a lot of synergies with the unit testing functionality for debugging.
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Miles | Miles wrote:
> Walter Bright wrote:
>> The problem in general with hiding pointers is that it'll break with a
>> moving garbage collector. You could work around this by 'pinning' the
>> objects, but pinning objects long term is a bad idea.
>
> Am I the only one who is screaming "OMG! What a hack!" while reading
> this thread?
>
> Sincerely, my impression of D dropped 2 points after reading the
> proposed solutions on this thread.
Yes, it is a hack, and an awful one. I think Frits and Thomas have it right in suggesting support for a 'weak pointer' that the GC updates for moves, but doesn't scan for roots.
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Georg Wrede | Georg Wrede wrote:
> Walter Bright wrote:
>> Looks like the deletion problem is a real issue. Let me think about it a bit.
>
> Hmm. A "big" SS implementation (see previous thread here "Dissecting the SS") c.f. like the 111 case, has more deletion related issues.
>
> In a non-trivial application one can almost take it for granted that there's instance pooling going on, too.
>
> A robust implementation would guarantee that any way the observer gets "removed" guarantees it also ceases to exist as an observer. This includes
>
> - getting deleted
> - simply not being referred to anymore
> - getting moved to the unused instances pool
That's right.
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lutger | Lutger wrote:
> Walter Bright wrote:
>> Lutger wrote:
>>> Almost, it's very simple, like the plain old function pointer as callback in C. The main difference is:
>>> - when an object which has member functions connected gets detroyed, there is no problem, no segfaults.
>>
>> Doesn't garbage collection automatically take care of that?
>
> Yes, but you'd have a reference to a dead object in your delegate array when it gets deleted and then you emit a signal. You can of course remove that reference when you so want to delete an object, then you have to track them and miss some ease of use. Or let some language / library do it for you.
I believe this was one of the reasons people have requested weak references for D. Though really, the same thing can be accomplished by registering a proxy class instead of a reference to the class to be signaled. I do this all the time in C++.
Sean
|
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don Clugston | Don Clugston wrote: > The most basic introspection would simply be, for each class and struct Typeinfo, add a pointer to a string that's just a concatenation of names and mangled types. > [name]\0[mangleof]\0[name]\0[mangleof]\0...[name]\0[mangleof]\0\0. > Since we have .alignof and .sizeof, this would allow all data members to be identified; and would allow code to be developed that could do serialization stuff. It would also be reasonably compact. > And an identical treatment for the functions in the vtable (just need to maintain the same order of functions). Given a string XXX, you could search for a function named "slotXXX" in the manglelist, and call the corresponding entry in the vtable. I think generating an array of TypeInfo's would be better, because they're easier to manipulate. TypeInfo instances are also singletons, which potentially could make it smaller than the mangle strings. 3 pieces of info are needed for each member: name typeinfo offset > It wouldn't deal with static functions (where you need the address as well as the name and type info) > I guess the challenging issue is to make sure that functions that aren't referenced don't get type info stored? I imagine those dynamic languages have trouble discarding unused functions at link time. I think you'd need to tell the compiler "don't discard this function even if you think it's not used, it's only referenced in a text string". The bloat might be bad enough that the full introspection info would only be generated for specified classes, say, ones that inherit from a special interface class. |
September 29, 2006 Re: Signals and Slots in D | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | For what it's worth, Andrei has written a number of articles involving S&S and concurrency. Though I don't know that they go much further than the Qt example you posted. Sean |
Copyright © 1999-2021 by the D Language Foundation