I have a wxBitmap that is to be used by two frames; rather than loading it twice, I store it in a kind of resource cache (an associative table: if given the bitmap identifier, it returns “the bitmap” - well, actually a wx_object reference like {wx_ref,67, wxBitmap,[]}).
I am under the impression that, when the first frame is closed, my bitmap gets deallocated (at least I have a {{badarg,"This"}, ...} whenever I fetch it from the cache and try to use it afterwards).
So, my questions:
for the cache itself: is there a good solution in order to detect such a “stale handle”? I do not think wx:is_null/1 is relevant (just checking the reference itself), and catching an exception thrown by wxBitmap:isOk/1 would be less than ideal
how can I prevent such a wx_object to be deallocated on frame deallocation at the first place: is there some way I can bump a reference counter, or make a cheap copy of a wx_object?
Thanks for your reply.
No, I am using a single environment, and I think it is correctly managed (each frame process is sent the only one created at initialization by a root supervisor), as I tracked it recently for another reason.
Yes, bitmaps are reference-counted by wxWidgets ; I imagined that a wx environment as a whole actually was accounting for a single reference, and that the “silent” bitmap deallocation could simply be explained by the fact that the whole widget hierarchy comprised by a frame is deleted by the destructor of that frame (said wxBitmap being held by a static wxStaticBitmap, owned ultimately by the closed frame).
So I regarded this bitmap deallocation as normal, but, in the case of a cache (or any term allowing a reuse of that bitmap), not desirable.
And thus a good solution could, rather than cheap-copying (not possible I think with current wx; for example the bitmap copy constructor does not seem to be available through the binding) or even reloading the bitmaps (what I do currently to circumvent this issue), be somehow to be able to increment (and later decrement) their reference counter. Or maybe I am misinterpreting. This would mean that no wx resource could be shared between windows?
(maybe that one could mess “directly” in wxWidgets with the ref counter, with Ref, unRef, etc., but it is almost certainly not a good idea anyway)
Actually a wx-level workaround suggested by your last answer might be to define a dummy, never-shown, never deallocated window that would be the parent of as many static bitmaps are there are bitmaps in said cache, thus preventing their deallocation when a frame referencing them is closed.
If/when a bitmap had to be evicted from that cache, then calling wxWindow:removeChild(DummyWindow, StaticBitmapToForget) on its static bitmap could/should be sufficient to trigger the deallocation of the corresponding bitmap I suppose.
Just to mark this topic as solved: no refcount workaround is actually needed; I had actually a screen that, when deleted, destructed all its resources, unfortunately including its bitmap ones (with wxBitmap:destroy/1), which was a mistake (as the cache was not aware of it).
So, as I understand it:
when creating a bitmap (e.g. with wxBitmap:new/2), the caller holds one reference onto that instance
thanks to the wxWidgets reference counting, bitmaps and similar wx_object can safely be included in widgets (windows), their life cycle will be automatically managed as their containers get created and destructed
to avoid memory leaks, wx users shall do an explicit management of such resources, by decrementing the (single) reference they got at creation, when this resource is not needed anymore; this may or may not lead to their direct destruction, and is to be done with, here, wxBitmap:destroy/1, as this function (whose documentation has a problem BTW) does not kill unconditionally the designated instance but just decrements its ref count
Hopefully this is correct! (please tell me if not!)