digitalmars.D.learn - How to make sure GC allocated resources stay around when used in C
- Gary Willoughby (46/46) May 12 2014 Based on this conversation in another thread:
- Kagamin (8/8) May 12 2014 AFAIK, addRoot is for memory allocated in GC heap, and addRange
- Gary Willoughby (4/12) May 12 2014 Ah yeah, i never thought, i could allocate Args on the GC heap.
- Kagamin (2/2) May 12 2014 Why many? I'd say, you typically have 0 subscriptions (label,
- Kagamin (3/3) May 12 2014 combobox and checkbox usually don't require a subscription
- Gary Willoughby (3/5) May 12 2014 There are many events that can be bound to on any widget.
- Kagamin (1/1) May 12 2014 Do you always bind all of them?
- Gary Willoughby (7/8) May 13 2014 They are not bound automatically but may be bound later. You can
- Kagamin (4/4) May 14 2014 It must be scanned, so you shouldn't specify NO_SCAN attribute,
- Gary Willoughby (10/24) May 14 2014 Ah yes. I've completed the changes and that has cured the
- Kagamin (8/9) May 14 2014 So they will be allocated on demand - only if it's bound, Args
- Kagamin (1/1) May 12 2014 Another option is to allocate from pool.
Based on this conversation in another thread: http://forum.dlang.org/thread/wdddgiowaidcojbrklsg forum.dlang.org?page=5#post-yjmrqgesjtadecutvk e:40forum.dlang.org I've realised i may have a nasty bug lurking in the code. Now i want to completely understand what is happening. Take the following code: struct Args { Element element; string uniqueData; Callback callback; } class Element { void foo(Callback callback, string uniqueData = null) { auto handler = function(ClientData data) { // Use data. }; auto cleanup = function(ClientData data) { free(data); }; Args* args = cast(Args*)malloc(Args.sizeof); (*args) = Args.init; (*args).element = this; (*args).uniqueData = uniqueData; (*args).callback = callback; c_function(handler, args, cleanup); } } I want to make sure that `callback` and `uniqueData` are never cleaned up by the GC until i wish to allow them to be freed. A comment was made that in the above scenario `callback` and `uniqueData` allow the potential of being cleaned up and that a call to `GC.addRoot` might fix this problem. Would it be as simple to just add: GC.addRoot(cast(void*)args); GC.setAttr(cast(void*)args, GC.BlkAttr.NO_MOVE); to the above example? Would this not allow collection until a call to GC.removeRoot(). Or do i have to handle `callback` and `uniqueData` individually? If so how do you stop a delegate and string from being cleaned up by the GC? Any help or explanations are very much appreciated. This is the actual production code: https://github.com/nomad-software/tkd/blob/master/source/tkd/element/element.d#L172
May 12 2014
AFAIK, addRoot is for memory allocated in GC heap, and addRange is for other types of memory, so you can't add non-gc memory as root (just a guess, see docs). I would allocate whole Args in GC heap and add is as root, yes, it would prevent collection until the root is removed. A better way would be to store Args in a linked list in the widget, this way it will be fully managed, and Args will live as long as the widget class instance references them without additional tinkering with GC.
May 12 2014
On Monday, 12 May 2014 at 19:13:28 UTC, Kagamin wrote:AFAIK, addRoot is for memory allocated in GC heap, and addRange is for other types of memory, so you can't add non-gc memory as root (just a guess, see docs). I would allocate whole Args in GC heap and add is as root, yes, it would prevent collection until the root is removed. A better way would be to store Args in a linked list in the widget, this way it will be fully managed, and Args will live as long as the widget class instance references them without additional tinkering with GC.Ah yeah, i never thought, i could allocate Args on the GC heap. I have to allocate it on the fly and not store it in the widget because there could be many. I'll have a fiddle.
May 12 2014
Why many? I'd say, you typically have 0 subscriptions (label, textbox) per widget, seldom - 1 (button, combobox, checkbox).
May 12 2014
combobox and checkbox usually don't require a subscription either. Only button requires a reaction from your code, everything else usually works on its own.
May 12 2014
On Monday, 12 May 2014 at 20:03:46 UTC, Kagamin wrote:Why many? I'd say, you typically have 0 subscriptions (label, textbox) per widget, seldom - 1 (button, combobox, checkbox).There are many events that can be bound to on any widget. https://github.com/nomad-software/tkd/blob/master/source/tkd/element/uielement.d#L328
May 12 2014
On Tuesday, 13 May 2014 at 06:27:14 UTC, Kagamin wrote:Do you always bind all of them?They are not bound automatically but may be bound later. You can bind to events such as mouse-enter, mouse-click, keypresses, etc. In fact this is how keyboard shortcuts are handled. I've added a potential fix to remove the allocation from the unmanaged heap and let the GC handle it. See what you think: https://github.com/nomad-software/tkd/commit/d77ff8603e26e7645c60b2613b996f1b21e751fc
May 13 2014
It must be scanned, so you shouldn't specify NO_SCAN attribute, it's for memory blocks, which are guaranteed to not hold pointers to GC memory, like ubyte[] buffers for i/o, so managed blocks can be safely collected without looking at content of NO_SCAN blocks.
May 14 2014
On Wednesday, 14 May 2014 at 07:11:45 UTC, Kagamin wrote:It must be scanned, so you shouldn't specify NO_SCAN attribute, it's for memory blocks, which are guaranteed to not hold pointers to GC memory, like ubyte[] buffers for i/o, so managed blocks can be safely collected without looking at content of NO_SCAN blocks.Ah yes. I've completed the changes and that has cured the problems i was experiencing and fixed a nasty bug. Thanks.Yes.They are not bound automatically but may be bound later.So they will be allocated on demand - only if it's bound, Args will be allocated,so widget will have only one Args allocated, or as many as were actually bound. Or do you want to save on one pointer per widget?By default most widget have none bound until a command or binding is added. Only one command can be added to widgets that support it (e.g. buttons) but all can have many events bound if the developer so wishes.Keyboard shortcuts are probably rare too, widgets should handle most common shortcuts like text editing or copying on their own without special handling by the user program, right?They do but you are free to bind actions to more events if you wish.
May 14 2014
On Tuesday, 13 May 2014 at 18:47:45 UTC, Gary Willoughby wrote:They are not bound automatically but may be bound later.So they will be allocated on demand - only if it's bound, Args will be allocated, so widget will have only one Args allocated, or as many as were actually bound. Or do you want to save on one pointer per widget? Keyboard shortcuts are probably rare too, widgets should handle most common shortcuts like text editing or copying on their own without special handling by the user program, right?
May 14 2014