BorlandTalk.com Forum Index BorlandTalk.com
Borland discussion newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Event Sinks

 
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (ActiveX)
View previous topic :: View next topic  
Author Message
Andrew
Guest





PostPosted: Fri Dec 05, 2003 11:47 am    Post subject: Event Sinks Reply with quote



Hi All,

I have a Remote Server COM object embedded into and application that runs on
a server computer (WIN2K Server), I run a client application on this server
and on a remote machine, I have many methods within the COM obect that run
fine and up until now have had few problems doing all that is necessary, now
I have the following scenario:

Client 1 tells the server that it has an alarm, this alarm is then sent
after 10 seconds to Client 2, both clients now display the the alarm, if
Client 1 selects the alarm I want to tell Client 2 to disable the ability
for its user to select that alarm, no problem, I use an event sink, I have
implemented the sink and when Client 1 selects the alarm it tells the server
that it has done so and in that method in the server I fire the
Fire_OnCallAccepted funtion, this should broadcast that the alarm is
accepted to all clients, or so I thought, the COM documentation I have read
suggests that this should happen but the Fire_OnCallAccepted funtion only
fires the event, in this case, in Client 1 and not Client 2. If Client 2
accepts the alarm Client 2 gets theFire_OnCallAccepted event.

Have I misread the documentation or am I doing something wrong, any advice
would be appreciated.

TIA

Andrew


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Dec 05, 2003 5:58 pm    Post subject: Re: Event Sinks Reply with quote




"Andrew" <alamb (AT) tynetec (DOT) co.uk> wrote


Quote:
in that method in the server I fire the Fire_OnCallAccepted funtion,
this should broadcast that the alarm is accepted to all clients, or so
I thought, the COM documentation I have read suggests that this
should happen but the Fire_OnCallAccepted funtion only fires the
event, in this case, in Client 1 and not Client 2. If Client 2 accepts
the alarm Client 2 gets theFire_OnCallAccepted event.

In theory, yes it is supposed to broadcast to all clients.

In practice, I find that is rarely the case. The implementation for
handling sink events does not keep track of multiple clients correctly, so
that when you call a Fire_...() function, it only knows about the calling
client.

To get around the problem in my own COM client objects, I maintain a global
list of all the client instances that have been created, and then when I
need to trigger an event I iterate through my list calling the event for
each client. For example:

--- TMyClientImp.h ---

class TMyClientImp :
...
{
public:
static TThreadList* AvailableClients;

TMyClientImp();
~TMyClientImp();

STDMETHOD(DoSomething());
};


--- TMyClientImp.cpp ---

TThreadList* TMyClientImp::AvailableClients = NULL;

TMyClientImp::TMyClientImp()
{
if( !AvailableClients )
AvailableClients = new TThreadList;
AvailableClients->Add(this);
}

TMyClientImp::~TMyClientImp()
{
if( AvailableClients )
{
TList *pList = AvailableClients->LockList();
pList->Remove(this);
int count = pList->Count;
AvailableClients->UnlockList();

if( count < 1 )
{
delete AvailableClients;
AvailableClients = NULL;
}
}
}

STDMETHODIMP TMyClientImp::DoSomething()
{
TMyClientImp *pIntf;
try
{
if( AvailableClients )
{
TList *pList = AvailableClients->LockList();
try
{
for(int x = 0; x < pList->Count; ++x)
{
pIntf = static_cast<TMyClientImp*>(pList->Items);
pIntf->Fire_DidSomething();
}
}
__finally {
AvailableClients->UnlockList();
}
}
}
catch(Exception &e)
{
return Error(e.Message, IID_IMyClient);
}
return S_OK;
}


Gambit



Back to top
Michael Harris
Guest





PostPosted: Fri Dec 05, 2003 8:11 pm    Post subject: Re: Event Sinks Reply with quote



This depends on the threading model also ... the contect is lost in Fire xxx
event.
The call appearantly goes to COM land somewhere<g> ..
You could also add your own CConnectionpoint Impl that uses a Global
interface to hold the event sinks.

There is an article on MSDN and one of the VC sites. search for
'CComDynamicUnkArray_GIT' <** IIRC **>
--
Michael


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Fri Dec 05, 2003 8:48 pm    Post subject: Re: Event Sinks Reply with quote


"Michael Harris" <techonos-NO-SPAM- (AT) attbi (DOT) com> wrote

Quote:
This depends on the threading model also ...

True. In my case, my COM servers are always free-threaded, so the
marshalling is handled automatically, although I do minimize the number of
threads accessing the interfaces when triggering events from one thread to
another.

Quote:
You could also add your own CConnectionpoint Impl that
uses a Global interface to hold the event sinks.

I do use connection points, actually. And the Fire_... functions do access
the connection point implementations, just not across multiple clients
correctly.

Quote:
There is an article on MSDN and one of the VC sites. search for
'CComDynamicUnkArray_GIT' <** IIRC **

That is for accessing the IGlobalInterfaceTable interface. That will handle
the marshalling of the eventsink/connectionpoint interfaces across threads
in the server, but that does not fix the original problem that the
interfaces are not being tracked correctly in the first place so that events
can be broadcasted.


Gambit



Back to top
Michael Harris
Guest





PostPosted: Fri Dec 05, 2003 11:10 pm    Post subject: Re: Event Sinks Reply with quote

Maybe the error is somewhere else....
for example. In the previous code sample, each TMyClientImp enters a
single TThreadList (AvailableClients).

So, the obvious question is. when multiple Clients Connect to the mentioned
server, are the connectionpoints piped into a single instance of the object
responsible for event notifiction ?

didin't think so.


--
Michael


Back to top
Remy Lebeau (TeamB)
Guest





PostPosted: Sat Dec 06, 2003 3:48 am    Post subject: Re: Event Sinks Reply with quote


"Michael Harris" <techonos-NO-SPAM- (AT) attbi (DOT) com> wrote


Quote:
In the previous code sample, each TMyClientImp enters
a single TThreadList (AvailableClients).

Correct.

Quote:
So, the obvious question is. when multiple Clients Connect
to the mentioned server, are the connectionpoints piped into
a single instance of the object responsible for event notifiction ?

Each client instance has its own connection point implementation, which is
supposed to be registered into a single list inside the ATL. But it doesn't
register correctly or something, because when the Fire_...() functions are
called, although they try to loop through a list somewhere, they only
execute the loop code once - for the calling client. So it would appear
that support for broadcasting events is not implemented correctly in the ATL
itself. Thus the workaround I use to keep my own list of client instances
so that I can then broadcast manually.


Gambit



Back to top
Michael Harris
Guest





PostPosted: Sat Dec 06, 2003 4:34 am    Post subject: Re: Event Sinks Reply with quote

Assuming the server exe is multi-use / multi-threaded ant the server app has
an automation server or just some com class called , say 'TServerImpl'.

each client will likely start its own object of type 'TServerImpl' inside
the server for each call to CocreateInstance or TComxx::Create even though
you may be using muti-use model.(many to one).
so, only the consectutive connections called from within a single clent
process would register with any particular instance of 'TServerImpl'.

Try a little experiment when you have time. in the server exe. in
'TServerImpl' , add
DECLARE_CLASSFACTORY_SINGLETON(TServerImpl)
in the impl code you want to share across client thread.

The connectionpoints will fail (because you are using a free threaded model)
But now you can fix them by using the GIT technique previously mentioned.

--
Michael


Remy Lebeau (TeamB)" wrote in message
Quote:

Each client instance has its own connection point implementation, which is
supposed to be registered into a single list inside the ATL. But it
doesn't
register correctly or something, because when the Fire_...() functions are
called, although they try to loop through a list somewhere, they only
execute the loop code once - for the calling client. So it would appear
that support for broadcasting events is not implemented correctly in the
ATL
itself. Thus the workaround I use to keep my own list of client instances
so that I can then broadcast manually.


Gambit





Back to top
Andrew
Guest





PostPosted: Mon Dec 08, 2003 9:05 am    Post subject: Re: Event Sinks Reply with quote

Hi,

Thanks for the replies, I'll look at those implementations.

Andrew


Back to top
Display posts from previous:   
Post new topic   Reply to topic    BorlandTalk.com Forum Index -> C++ Builder (ActiveX) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.