Re: Threads, Message Pump and Sync
Hi Joe,
****
Essentially, you cannot dismiss the dialog until the producer thread fini=
shes, but you've
already established that. When the producer thread terminates successf=
ully, and sends the
"thread end" notification, then you can start the gc thread ON THAT COLLE=
CTION OF OBJECTS.
So it would make no sense to add other objects from a potential dialog 2 =
which uses a new
producer thread to the collection that already exists, and therefore, no =
synchronization
should be necessary.
Your failure seems to be that you think of A collection of objects
to be deleted, when the correct model is to think of a PER-DIALOG collect=
ion of objects to
be deleted, and due to the fundamentally asynchrononous nature of your gc=
thread, you need
a queue of objects to be deleted.
Stop thinking of having A structure to represent your gc collection, and =
have a PER-DiALOG
structure.
Actually, this is EXACTLY what I was doing all along. In my earlier
post, I mentioned " a list of SETS of items "... where each SET
represents the items to be deallocated of a dimissed dialog.
Here is the actual implementation of the GC class:
void CGC::GCCleanUp()
{
BOOL bRun = FALSE;
int iUpperBound = 0;
EnterCriticalSection(&m_csGB);
iUpperBound = m_SetOfItemsArray.GetUpperBound(); // This actually has
arrays as elements.
if (iUpperBound != -1)
bRun = TRUE; // AT LEAST ONE SET OF ITEMS NEEDS TO BE DEALLOCATED
LeaveCriticalSection(&m_csGB);
while (bRun) // upperbound may be modified by GUI.
{
CTypedPtrArray<CObArray, CVEListBoxItem* >* pSetOfItems =
m_SetOfItemsArray.GetAt(0);
if (pSetOfItems)
{
int iUpperBound = pSetOfItems->GetUpperBound(); // This will not
change as the dialog associated with this set has been dismissed.
for (int i = 0; i <= iUpperBound; ++i)
{
CVEListBoxItem* pItem = NULL;
pItem = pSetOfItems->GetAt(i);
if (pItem)
delete pItem;
}
pSetOfItems->RemoveAll();
delete pSetOfItems;
pSetOfItems = NULL;
}
EnterCriticalSection(&m_csGB);
m_SetOfItemsArray.RemoveAt(0);
iUpperBound = m_SetOfItemsArray.GetUpperBound();
if (iUpperBound == -1) // Anything new arrived for deletion or are
we already done?
bRun = FALSE; // If not, we are done, otherwise we, again, are
guaranteed to have AT LEAST ONE MORE SET to be deallocated and thus we
may continue to loop.
LeaveCriticalSection(&m_csGB);
}
This is how I have this implemented.
The "AddToCleanUp" is essentially this:
void CGC::AddToCleanUp(CTypedPtrArray<CObArray, CVEListBoxItem* >*
pArray)
{
EnterCriticalSection(&m_csGB); // Critical section is used because
this function is called from the UI thread.
m_SetOfItemsArray.Add(pArray);
LeaveCriticalSection(&m_csGB);
SetEvent(m_hCleanupEvent); // New set of items to be de-allocated
arrived. Need to start deallocating them (GCCleanUp will be executed).
}
What do you think ?
Marius