slow memory release (refcounted structure) - Is my workaround a good way?

234 views Asked by At

in my program i can load a Catalog: ICatalog

a Catalog here contains a lot of refcounted structures (Icollections of IItems, IElements, IRules, etc.)

when I want to change to another catalog, I load a new Catalog but the automatic release of the previous ICatalog instance takes time, freezing my application for 2 second or more.

my question is :

I want to defer the release of the old (and no more used) ICatalog instance to another thread.

I've not tested it already, but I intend to create a new thread with :

ErazerThread.OldCatalog := Catalog; // old catalog refcount jumps to 2
Catalog := LoadNewCatalog(...);     // old catalog refcount =1
ErazerThread.Execute;               //just set OldCatalog to nil.

this way, I expect the release to occur in the thread, and my application not beeing freezed anymore.

Is it safe (and good practice) ?
Do you have examples of existing code already perfoming release with a similar method ?

2

There are 2 answers

3
Marco van de Voort On BEST ANSWER

I would let such thread block on some threadsafe queue(*), and push the interfaces to release into that queue as iunknowns.

Note however that if the releasing touches a lock that your memory manager uses (like a global heapmanager lock), then this is futile, since your mainthread will block on the first heapmanager access.

With a heapmanager with per thread pools, allocating many items in one thread and releasing it in a different thread might frustrate coalescing and reuse of (small) blocks algorithms.

I still think the way you describe is generally sound when implemented properly. But this is from a theoretic perspective to show that there might be a link from the 2nd thread to the mainthread via the heapmanager.

(*) Simplest way is to add it to a tthreadlist and use tevent to signal that an element was added.

0
Rob Kennedy On

That looks OK, but don't call the thread's Execute method directly; that will run the thread object's code in the current thread instead of the one that the thread object creates. Call Start or Resume instead.