Re: Independent thread fireing events in ATL Service synchronization requirements?

From: Alexander Nickolov (agnickolov_at_mvps.org)
Date: 09/16/04


Date: Thu, 16 Sep 2004 14:41:14 -0700

It didn't make much sense. If m_nSize is zero (there's no
m_pSize), that means you have no entries in the sink array
and hence the loop will not execute, much less crash.
m_vec itself is not a pointer, so it cannot be NULL for sure.
Can you state the exact problem in clear consistent terms?
And post the proxy method for illustration perhaps?

-- 
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnickolov@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================
<pt@dafweb.com> wrote in message 
news:%238cc7fBnEHA.2708@TK2MSFTNGP10.phx.gbl...
> Yes, I did lock while adding and removing objects
> from my global list. Indeed, as I mentioned in my previous post,
> the problem is NOT with the object itself,
> the pointer is valid and the object is NOT gone.
> The problem is with the variable "m_vec" which  is null,
> despite the COM object valid state.
>
> Please re-read my previous post for details.
>
> I do use a dedicated thread to fire events.
>
> My VBA event handler simply write a log using
> "debug.print ...."
>
> Thank you for your help.
>
> Phil. Ten.
>
>
> "Alexander Nickolov" <agnickolov@mvps.org> wrote in message
> news:%23PSThEBnEHA.3396@tk2msftngp13.phx.gbl...
>> Did you lock while adding and removing your objects to the list?
>> If you did this porperly, your object cannot be gone while you
>> are firing the events, since the lock is maintained around the entire
>> loop. However, make sure you have a dedicated thread for
>> event firing, and that no object is destroyed within the event
>> handler, otherwise locking may not be sufficient (due to reentrancy).
>>
>> -- 
>> =====================================
>> Alexander Nickolov
>> Microsoft MVP [VC], MCSD
>> email: agnickolov@mvps.org
>> MVP VC FAQ: http://www.mvps.org/vcfaq
>> =====================================
>>
>> "Phil Ten" <pt@dafweb.com> wrote in message
>> news:eTX34C%23mEHA.3428@TK2MSFTNGP11.phx.gbl...
>> > Thank you for your post. I followed your recommandations
>> > and made my client list a class with synchronization inside
>> > and a lock around the entire loop.
>> >
>> > To test if closing the COM object while firing events is handled
>> > correctly, I modified my external thread so it would continuously
>> > fire events. Then using a VBA application I create and delete
>> > the COM object also continuously.
>> >
>> > Most of the time it works fine, however, from time to time
>> > I get an exception. In the debugger I could see that the
>> > pointer on my COM object is valid (thanks to the
>> > synchronization inside the client list class) but variable
>> > m_vec is null (m_pSize=0, m_ppUnk=0x0000000).
>> >
>> > Unfortunately, the ATL code inside the CProxy_XXXX class in the
>> > Fire_XXXXX function tries to execute
>> >
>> > CComPtr<IUnknown> punkConnection = m_vec.GetAt(iConnection);
>> >
>> > which fails since m_vec is NULL.
>> >
>> > At this point, my guess is that the lock for the COM object
>> > pointer is not enough and that I would also need to lock
>> > somehow the connection with the client???
>> >
>> > Thanks again for your help.
>> >
>> > Phil. Ten.
>> >
>> >
>> >
>> > "Alexander Nickolov" <agnickolov@mvps.org> wrote in message
>> > news:eCY3dS0mEHA.3328@TK2MSFTNGP10.phx.gbl...
>> >> You'll need synchronization for your list all right. The best place
>> >> would be in your global class of course. E.g. instead of using
>> >> STL list directly, wrap it in a class that exposes methods for
>> >> your objects to call and those methods provide the necessary
>> >> synchronization. This falls under my last comment - you need
>> >> proper synchronization for your data. The iteration will be a
>> >> bottleneck, however, since you need to maintain the lock around
>> >> the entire loop notifying your objects.
>> >>
>> >> -- 
>> >> =====================================
>> >> Alexander Nickolov
>> >> Microsoft MVP [VC], MCSD
>> >> email: agnickolov@mvps.org
>> >> MVP VC FAQ: http://www.mvps.org/vcfaq
>> >> =====================================
>> >>
>> >> "Phil Ten" <pt@dafweb.com> wrote in message
>> >> news:Or5$7gwmEHA.556@tk2msftngp13.phx.gbl...
>> >> > Sorry, I sent the previous post by mistake before finishing it.
>> >> >
>> >> > Thanks again for your post. It helps but the answer to my first
>> >> > point in my initial post is still unclear for me.
>> >> >
>> >> > I will rephrase it here. I currently maintain a list of all
>> >> > active instances of my COM object by adding the pointer
>> >> > on the object to an STL list in the constructor of the object:
>> >> >
>> >> > CDirWatch::CDirWatch()
>> >> > {
>> >> >    ClientsList.insert(this);
>> >> > }
>> >> >
>> >> > I remove the pointer from my list in the destructor of the
>> >> > COM obect:
>> >> >
>> >> > CDirWatch::~CDirWatch()
>> >> > {
>> >> >    ClientsList.erase(this);
>> >> > }
>> >> >
>> >> > My independent thread fires event using all pointers
>> >> > found in the list:
>> >> >
>> >> > CDirWatchItemList::iterator i;
>> >> > for (i=ClientsList.begin();i!=ClientsList.end();i++)
>> >> > {
>> >> >    (*i)->Fire_Notification(MyData);
>> >> > }
>> >> >
>> >> > My questions are:
>> >> >
>> >> > 1) Is the COM object Constructor/Destructor a good
>> >> > location to add/remove pointers from my global list?
>> >> >
>> >> > 2) Obviously, for each loop the object may have been
>> >> > destroyed just after extracting the pointer out of my list
>> >> > and therefore the call to "Fire_Notification" will fail
>> >> > because the pointer is no longer valid. How could I
>> >> > lock all existing COM instances while I loop though the
>> >> > list and fire events?
>> >> >
>> >> > Thanks again for all help.
>> >> >
>> >> > Phil Ten
>> >> >
>> >> >
>> >> > "Alexander Nickolov" <agnickolov@mvps.org> wrote in message
>> >> > news:O0t8JIqmEHA.1652@TK2MSFTNGP09.phx.gbl...
>> >> >> Ok, you need synchronization in the code manipulating and
>> >> >> accessing the m_vec array of sink pointers. ATL already does
>> >> >> this for you in two places - IConnectionPointImpl<> and the
>> >> >> proxy class used for firing your events. If you don't deviate
>> >> >> from these two, you don't need any extra synchronization in
>> >> >> your code as far as firing the events. Any extra synchronization
>> >> >> with regards to your object's internal state is entirely up to you.
>> >> >> I hope this answers your question.
>> >> >>
>> >> >> -- 
>> >> >> =====================================
>> >> >> Alexander Nickolov
>> >> >> Microsoft MVP [VC], MCSD
>> >> >> email: agnickolov@mvps.org
>> >> >> MVP VC FAQ: http://www.mvps.org/vcfaq
>> >> >> =====================================
>> >> >>
>> >> >> "Phil Ten" <pt@dafweb.com> wrote in message
>> >> >> news:ut7yzHpmEHA.1652@TK2MSFTNGP09.phx.gbl...
>> >> >> > Thank you for your post.
>> >> >> >
>> >> >> > I specified the free threading model for my object.
>> >> >> >
>> >> >> > I use ATL 7, I defined _ATL_FREE_THREADED in the
>> >> >> > StdAfx.h file. I checked how the code is initializing, and
>> >> >> > I could see that "CoInitializeEx(NULL, COINIT_MULTITHREADED)"
>> >> >> > is called.
>> >> >> >
>> >> >> > I hope this is the information you requested.
>> >> >> >
>> >> >> > Thanks again for all help.
>> >> >> >
>> >> >> > Phil. Ten.
>> >> >> >
>> >> >> >
>> >> >> > "Alexander Nickolov" <agnickolov@mvps.org> wrote in message
>> >> >> > news:OUQfYSomEHA.4068@tk2msftngp13.phx.gbl...
>> >> >> >> The most important question to ask first is: what is the
>> >> >> >> threading model of your object? Depending on the answer
>> >> >> >> you proceed completely differently.
>> >> >> >>
>> >> >> >> -- 
>> >> >> >> =====================================
>> >> >> >> Alexander Nickolov
>> >> >> >> Microsoft MVP [VC], MCSD
>> >> >> >> email: agnickolov@mvps.org
>> >> >> >> MVP VC FAQ: http://www.mvps.org/vcfaq
>> >> >> >> =====================================
>> >> >> >>
>> >> >> >> "Phil Ten" <pt@dafweb.com> wrote in message
>> >> >> >> news:ePmX5vjmEHA.4064@TK2MSFTNGP14.phx.gbl...
>> >> >> >> > Hello,
>> >> >> >> >
>> >> >> >> > I am writing an ATL service which fires events
>> >> >> >> > from an independent thread.
>> >> >> >> >
>> >> >> >> > My base code to fires events seem to work correctly.
>> >> >> >> > However, I still to need to implement synchronization
>> >> >> >> > features to fire events only when possible. I am
>> >> >> >> > familar with threads synchronization functions but,
>> >> >> >> > for this project (COM objects in an ATL
>> >> >> >> > service) I have no idea where I should implement
>> >> >> >> > my synchronization routines.
>> >> >> >> >
>> >> >> >> > In particular, I can see these two points:
>> >> >> >> >
>> >> >> >> > 1) Do my need to maintain my own global list of pointers
>> >> >> >> > pointing active COM clients, or is there a way
>> >> >> >> > to retreive such a list?
>> >> >> >> >
>> >> >> >> > If I must maintain my own list of pointers, where
>> >> >> >> > should I implement my code in the COM object class
>> >> >> >> > to add/remove items to my global list?
>> >> >> >> >
>> >> >> >> > 2) I assume that when the independent thread fires an event,
>> >> >> >> > I must use synchronization routines to be sure that
>> >> >> >> > the COM client will remain usable until the return of
>> >> >> >> > the fire_event function. If this is correct, where in the
>> >> >> >> > COM object classshould I implement my synchronization routines
>> >> >> >> > for this purpose?
>> >> >> >> >
>> >> >> >> > 3) Is there other pitfalls I should be aware of?
>> >> >> >> >
>> >> >> >> > Thank you in advance for all help.
>> >> >> >> >
>> >> >> >> > Phil. Ten.
>> >> >> >> >
>> >> >> >> >
>> >> >> >> >
>> >> >> >>
>> >> >> >>
>> >> >> >
>> >> >> >
>> >> >>
>> >> >>
>> >> >
>> >> >
>> >>
>> >>
>> >
>> >
>>
>>
>
>