i'd like to perform some actions on a particular entity after there are no longer any references to it, but before the garbage collector wipes its data out. i'm using this for an experiment with more "purely functional" gui abstractions. here is what i'd like to do:
(let [window (make-window width height)] ; A
(various-actions window)
(let [window (resize window new-width new-height)] ; B
(more-actions window))
(and-more-actions window)) ; C
at A a window instance is created with a width and height. eventually i want to change the window at B. the code treats this like an immutable action, but underneath the window will simply change to reflect the changes. actions performed on the A scope's window while the B scope's window exists (in case of multithreading) would not be allowed in some manner.
at C after we finish doing stuff at B and leave that let scope, the B window object will be unreferenced and garbage collected. but i want to signal the underlying window mechanism that it should roll back the B changes now, and accept A scope activity again. thus action at C will be as though B effects didn't happen.
as well, if the top level A window is no longer referenced, it should destruct itself in whatever manner before garbage collection.
i could possibly manage this by having make-window modify a global state which registers window references, but i'm not sure how to detect the point at which the B scope reference is lost. how can i check the references to a piece of data? or is there some other way to address this problem?
i realize this is a somewhat convoluted set-up, but i want to find a way to reconcile the statefulness of gui programming and make it appear to be as pure as possible.
This is not the way to build a correct program. A correctly-written program cannot assume that garbage collection is ever run, and certainly it won't run as instantaneously as you'd like in order to make a UI decision based on it.
It's not at all clear from your problem description what you actually want to do, but tying it to garbage collection is sure to be the wrong way to do it. Perhaps you could add some code after leaving B that will do whatever it is that you want.
Related
TL;DR
How do I correctly pass information, wrapped as a QObject to QML in a signal that might be emitted with high frequency, reducing overhead, ensuring the object/reference outlives at least the execution of the connected slots?
I have a C++ QObject registered as QML type. This object has some signal
void someSignal(InformationQObject* someInformation)
in which I don't pass all the information in seperate parameters but in one object - similar to the signals found e.g. in the MouseArea whith e.g. the signal
void clicked(QQuickMouseEvent *mouse)
Now I am wondering about the right lifetime management of this someInformation.
So far, in my object, I have a member:
InformationQObject* m_lastInformation
and to send the signal I use:
void sendMySignal(/* possible params */)
{
delete m_lastInformation
m_lastInformation = new InformationQObject(/* right params here */)
emit someSignal(m_lastInformation)
}
Now this seems wrong.
Reasons: If you look at the implementation of the QQuickMouseArea they do it differently. Seemingly they don't create a new object for each event but recycle the existing one, seemingly. I find it hard to follow all their sources but I think this comment from one of their files gives a good reason:
QQuickPointerEvent is used as a long-lived object to store data related to
an event from a pointing device, such as a mouse, touch or tablet event,
during event delivery. It also provides properties which may be used later
to expose the event to QML, the same as is done with QQuickMouseEvent,
QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be
delivered at a time, this class is effectively a singleton. We don't worry
about the QObject overhead because the instances are long-lived: we don't
dynamically create and destroy objects of this type for each event.
But this is where it gets to complicated for me to see through, how they do it. This comment is regarding a QQuickPointerEvent. There exists a QQuickPointerMouseEvent. In their signal they pass a QQuickMouseEvent*
The latter is a pointer to one of their members QQuickMouseEvent quickMouseEvent.
At some point, somehow, this pointer becomes invalid in QML
MouseArea {
anchors.fill: parent
property var firstEvent
onClicked: {
if (firstEvent === undefined) firstEvent = mouse
console.log(mouse.x, mouse.y)
console.log(firstEvent.x, firstEvent.y) // -> TypeError on second and consecutive clicks.
}
}
So there must be some magic happening, that I don't understand.
You are opening a can of worms. QML lifetime management is broken in above-trivial scenarios, and the API doesn't really give you a meaningful way to walk around that. The solution for me has been to set the ownership to CPP and manually manage the object lifetime. Primitive I know, but the only solution to avoid deletion of objects still in use and actual hard crashes.
If mouse area recycled the same event object, it wouldn't become invalid on the subsequent click.
If your code reflects your actual usage scenario, I recommend you simply copy the individual event properties rather than attempting to store the actual event, either in dedicated properties, or as a JS object if you want to avoid overhead and don't need notifications. I tend to use arrays, and rely on the faster index access.
Another solution I can recommend is a Q_GADGET with a PIMPL - gadgets are limited by design so they cannot be passed as pointers, and they are always copied by value, but you can have the actual object only contain a pointer to the heavier data implementation, and only serve as an accessor and interface to access the data from QML. This way you can reuse the data stuff, with the actual object value being negligible, as it will essentially just be a pointer and involve no dynamic memory allocation whatsoever. You can additionally expose the actual data as an opaque object for the sake of copying that to other gadgets and use ref counting to manage the data lifetime.
I'm writing a small MFC app and loading an icon handle like this in my executable upon launch:
const HANDLE hIconLarge = ::LoadImage(AfxGetInstanceHandle()
MAKEINTRESOURCE(IDI_EXAMPLE), IMAGE_ICON,
::GetSystemMetrics(SM_CXICON), ::GetSystemMetrics(SM_CYICON), 0);
I am retaining this same handle in another class in a DLL I created by simply assigning it like this:
m_hLargeWindowIcon = p_hLargeIconHandle;
where m_hLargeWindowIcon is a private class HANDLE variable in a singleton that I call IconManager. I then later occasionally use this icon handle to set the large icon for pop-up windows that my DLL creates.
It seems to be working fine, but I am concerned about the life cycle of the handle I am retaining.
Is it safe to save a handle in this fashion (i.e. the handle will remain valid until the host process of my DLL is terminated) or can I run into issues where the handle may not be valid when I access it at a later point in time? Should I be using DuplicateHandle or something to that nature in this case?
You don't need to duplicate the handle in any way. Your usage is fine, apart from the fact that you are using the wrong type. Instead of HANDLE you should use HICON.
When nothing more refers to that icon handle, you do need to destroy it. Call DestroyIcon to do so.
The lifetime of the icon is as long as a valid handle to it (HICON) exists, else, it'll get cleaned up when the process exits.
Normally you would want to wrap the functionality up in a Icon class of some sort with appropriate copy and move semantics. Or at the very least tie it to a RAII class to manage the lifetime of the HICON.
Given the singleton nature of its use here, that may be overkill. Let the singleton clean it up DestroyIcon when the program exits. One caveat here is that you really should be sure that clients of the code don't try clean it up for you. Once they have a bit copy, sure, there is little you can do to stop them, but at least be clear in the documentation how the code behaves and some reason as to why (since this seems to be a corner case w.r.t. the resource management).
Side note: I believe the correct function to duplicate an icon is CopyIcon.
I use DispEventAdvise in a BHO in order to capture onclick events of a specific checkbox. You can see the code in my previous question (although it's not that relevant).
In order to be able to call DispEventUnadvise later, I keep a reference to the IHTMLElement object of the checkbox.
When should I call DispEventUnadvise? Is there a way to know when the checkbox is going away?
Is it even legal to keep a reference to the IHTMLElement object? I mean, when the page is destroyed, and there's still a reference to the object of that checkbox, what happens to it?
You are expected to unadvise from event source/connection point when you no longer want to receive events. The call, in particular, make the connection point release your sink interface pointer. Before unadvising, connection point holds a reference and extends your sink object lifetime.
That is, you call it any time you want to opt out, there is no specific good time where you should do it at, other than general considerations.
The other part of the question "when checkbox is going away" however is not related directly. Being connected to connection point you don't receive "going away" notification. It is legal to keep holding an interface pointer even if the entire page went away: the checkbox, alone or together with its owner, will remain in terminating state until all external references (including yours) are released. As a part of safe termination, when the page/document goes away it might strip connection point connections from its side because no events are going to follow and the document is doing sanity cleanup to avoid circular references and leaks.
In your case, I suppose your best way out is to find another suitable event to see when the entire document goes away and assume that checkbox is going away as well. Another [less safe] option is to watch your sink interface object: once its external reference is unexpectedly release by connection point, it means that its doing cleanup and checkbox is going away.
I've been working a lot with Win32 lately, but I'm pretty new to it, and need some advice concerning organization. In C++, although it works syntactically to declare global variables, I was always under the impression that this was sloppy, because the variable can then be modified anywhere, so it becomes much more difficult to track changes to it.
In my Win32 project, I've got several variables which need to be modified in multiple places. For instance, one such variable was in the WndProc function and also in a dialog procedure function. Due to the way it was used, I was able to simply use the actual values in WndProc, and then call the dialog box using DialogBoxParam, and pass the value to the dialog box through the lParam value.
However, there are other values, such as certain bitmaps that I use for drawing or variables that are used in multiple different window message calls, where the value(s) need to be retained throughout multiple instances of the WndProc function or multiple functions. I can control the parameters of the functions I created, but what if I need to pass a variable into the WndProc function so that I can use it regardless of multiple different window messages? What if I need to pass in multiple values?
So far I've just been making everything global, and it works, but it feels sloppy to me...but I know that some variables are generally global as a matter of convention - like the main window and instance variables.
What do you all think?
It might help if you had a specific example in code. But I think you're talking about lifetime--you have a resource (say a bitmap) and you need to reference it many times in response to different Windows messages. You could make it global, yes, but I agree that's sloppy.
So who created the window? Likely your "App" class or something along those lines. Since that class's lifetime is logically longer than the window's, it could hold the resources required by the window.
Or a better approach is to create a "Window" class. Your App instantiates a Window object. The Window object creates the Win32 window and holds the HWND (you've now abstracted that away from the App so it doesn't need to know those gory details), and the Window instance can hold the bitmap resources.
Instead of using global variables you can store window-specific data in a C++ object associated with the relevant window.
To associate a C++ object with a window, use any of a number of existing C++ class frameworks (such as e.g. Microsoft’ WTL or Torjo's Win32GUI), or do it yourself by using SetWindowSubclass API function.
For the Do It Yourself™ solution, I presented a complete C++ example in another SO answer.
That said, for a tiny little program global variables + a dialog is the easiest and presents no problems. So in general, use the Right Tool™ for the job. For larger jobs, use more heavy tooling…
I'm working on a game and I'm currently working on the part that handles input. Three classes are involved here, there's the ProjectInstance class which starts the level and stuff, there's a GameController which will handle the input, and a PlayerEntity which will be influenced by the controls as determined by the GameController. Upon starting the level the ProjectInstance creates the GameController, and it will call its EvaluateControls method in the Step method, which is called inside the game loop. The EvaluateControls method looks a bit like this:
void CGameController::EvaluateControls(CInputBindings *pib) {
// if no player yet
if (gc_ppePlayer == NULL) {
// create it
Handle<CPlayerEntityProperties> hep = memNew(CPlayerEntityProperties);
gc_ppePlayer = (CPlayerEntity *)hep->SpawnEntity();
memDelete((CPlayerEntityProperties *)hep);
ASSERT(gc_ppePlayer != NULL);
return;
}
// handles controls here
}
This function is called correctly and the assert never triggers. However, every time this function is called, gc_ppePlayer is set to NULL. As you can see it's not a local variable going out of scope. The only place gc_ppePlayer can be set to NULL is in the constructor or possibly in the destructor, neither of which are being called in between the calls to EvaluateControls. When debugging, gc_ppePlayer receives a correct and expected value before the return. When I press F10 one more time and the cursor is at the closing brace, the value changes to 0xffffffff. I'm at a loss here, how can this happen? Anyone?
set a watch point on gc_ppePlayer == NULL when the value of that expression changes (to NULL or from NULL) the debugger will point you to exactly where it happened.
Try that and see what happens. Look for unterminated strings or mempcy copying into memory that is too small etc ... usually that is the cause of the problem of global/stack variables being overwritten randomly.
To add a watchpoint in VS2005 (instructions by brone)
Go to Breakpoints window
Click New,
Click Data breakpoint. Enter
&gc_ppePlayer in Address box, leave
other values alone.
Then run.
When gc_ppePlayer changes,
breakpoint
will be hit. – brone
Are you debugging a Release or Debug configuration? In release build configuration, what you see in the debugger isn't always true. Optimisations are made, and this can make the watch window show quirky values like you are seeing.
Are you actually seeing the ASSERT triggering? ASSERTs are normally compiled out of Release builds, so I'm guessing you are debugging a release build which is why the ASSERT isn't causing the application to terminate.
I would recommend build a Debug version of the software, and then seeing if gc_ppePlayer is really NULL. If it really is, maybe you are seeing memory heap corruption of some sort where this pointer is being overridden. But if it was memory corruption, it would generally be much less deterministic than you are describing.
As an aside, using global pointer values like this is generally considered bad practice. See if you can replace this with a singleton class if it is truly a single object and needs to be globally accessible.
My first thought is to say that SpawnEntity() is returning a pointer to an internal member that is getting "cleared" when memDelete() is called. It's not clear to me when the pointer is set to 0xffffffff, but if it occurs during the call to memDelete(), then this explains why your ASSERT is not firing - 0xffffffff is not the same as NULL.
How long has it been since you've rebuilt the entire code base? I've seen memory problems like this every now and again that are cleared up by simply rebuilding the entire solution.
Have you tried doing a step into (F11) instead of the step over (F10) at the end of the function? Although your example doesn't show any local variables, perhaps you left some out for the sake of simplicity. If so, F11 will (hopefully) step into the destructors for any of those variables, allowing you to see if one of them is causing the problem.
You have a "fandango on core."
The dynamic initialization is overwriting assorted bits (sic) of memory.
Either directly, or indirectly, the global is being overwritten.
where is the global in memory relative to the heap?
binary chop the dynamically initialized portion until the problem goes away.
(comment out half at a time, recursively)
Depending on what platform you are on there are tools (free or paid) that can quickly figure out this sort of memory issue.
Off the top of my head:
Valgrind
Rational Purify