Re: COM calls reentering in STA
Scott McPhillips [MVP] <org-dot-mvps-at-scottmcp> wrote:
Initially, client calls server passing a pointer to a client callback
object. So the thread that receives this initial call is the "main"
and puts the pointer into the GIT so other threads can use a
marshalled pointer. Your comments make me wonder what the point of
the GIT marshalling is.
Your server would probably be simpler if you let all threads join MTA.
Then you won't need GIT.
As it stands, if you try to pass a proxy pointer to another STA thread
without marshalling, that second thread will get RPC_E_WRONG_THREAD
error on every call trough that proxy. Proxies are only valid in one
apartment they were marshalled for.
A quick look at
IMessageFilter looks real scary: I don't want to "reject" calls, just
make them wait.
That's what SERVERCALL_RETRYLATER is for. But you probably don't want to
install your own IMessageFilter: chances are, your host application has
already installed its own and is relying on it. You can only install one
message filter per thread (though you get the previous one back and
could, in principle, chain to it; I've never tried that myself).
So it seems to me I will need to protect all the
server's callback calls with a critical section. Any other possible
approaches?
It really depends on what your callback needs to do. One more or less
general approach goes something like this:
MyClient::MyCallback(param) {
static bool in_callback = false;
if (in_callback) {
// reentrant call
actionQueue.push(param);
return S_OK;
}
in_callback = true;
PerformAction();
in_callback = false;
while (!actionQueue.empty()) {
MyCallback(actionQueue.top());
actionQueue.pop();
}
}
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925