1

I could not find the definite answer to the following question: if a COM class is thread safe, that is it is marked with Both or Free, do I really need to marshal its object interface to pass it to another thread in the same process? I do not ask about the case if both threads belong to MTA, I ask about the case when each thread belongs to it's own STA.

I know about the rule to marshal interfaces between threads which belong to different apartments, my question is what happens if I pass a raw interface pointer to a thread in a different apartment and each thread calls methods on the object which is thread safe?

According to my experience it works fine, my question is, if it is a matter of time, and dangerous and could lead to a crash because of any reason, or it's completely safe and just nice to have rule?

Niall
  • 28,102
  • 9
  • 90
  • 124
andrebroz
  • 95
  • 7

1 Answers1

2

TL;DR - always marshal... always.

Why? COM then knows about it and will do the right thing...

... do I really need to marshal its object interface to pass it to another thread in the same process?

Yes. Always.

The COM rule here is that accessing a COM object must always be done in the same apartment (read on the same thread for STAs) as it was created in. If you subvert this (even if it appears to work), you can run into a deadlock between COM calls because objects in separate apartments land up waiting on each other.

If COM sees that the source and target apartments of the marshal is the MTA, it won't impose any overhead. It will also be able to managed the callbacks to other apartments as required.

... if a COM class is thread safe, that is it is marked with Both or Free...

What this means is that the object can be used in either apartment types. It is at the point of creation that the apartment in which it will live is decided.

According to my experience it works fine, my question is if it is a matter of time, dangerous and leading to crash because of any reason, or it's completely safe and just nice to have rule?

Subverting the COM threading model generally lands up in tears - quiet possibly years after the initial offence. It is a ticking time bomb. Don't do it.


As noted in the comments, there is CoCreateFreeThreadedMarshaler, but as mentioned in the remarks in the linked documentation, it requires "... a calculated violation of the rules of COM...", and does hint at a non-general or narrow band of applicability.

Niall
  • 28,102
  • 9
  • 90
  • 124
  • 1
    No problem, its a pleasure. – Niall Jul 19 '16 at 09:42
  • 2
    There's one exception - a so-called "thread-neutral" object, an object that aggregates free-threaded marshaler (see [`CoCreateFreeThreadedMarshaler`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms694500.aspx)). For such an object, it is known that marshaling would result in raw pointer being passed to another thread as-is, so one can as well skip the dance. This can only be done for your own objects - there's no way to tell whether or not a random third-party interface pointer aggregates FTM; it's purposefully designed to be transparent. – Igor Tandetnik Jul 19 '16 at 13:22
  • 1
    @IgorTandetnik. Didn't know about that function, thanks for the link. I do note the following from the remarks section - _"... a calculated violation of the rules of COM..."_ It does hint at a narrow band of applicability. – Niall Jul 19 '16 at 13:36
  • What about FreeThreadedDOMDocument? Does it mean it contains FTM or it's just thread safe? – andrebroz Jul 20 '16 at 11:09
  • I looked in OveView, it's marked as Both. As far as I understand if it were marked as Neutral, then it would contain FTM? – andrebroz Jul 20 '16 at 11:25
  • 1
    @andrebroz. I don't have a reference immediately available on the `FreeThreadedDOMDocument`. Your question could make for a new SO question. – Niall Jul 20 '16 at 11:38
  • @Niall Thank you for a good advice, I will add it as a new question. – andrebroz Jul 21 '16 at 12:01
  • 1
    @andrebroz, however, there's a neutral apartment, so neutral objects run in a specific context and object marshaling happens transparently, unlike free-threaded objects (an in-process proxy shouldn't incur serialization). Whereas, a free-threaded object runs in whatever is the current apartment, its lifetime is tied to the apartment where it was created and object marshaling must be handled manually (an in-process proxy is a direct pointer). What they have in common is that they run fine under any COM-aware thread. – acelent Jul 25 '16 at 01:11
  • @acelent, thank you for your comment, can you explain please what is the implementation difference between COM classes that marked Both or Free and Neutral? As far as I understand they all should be thread safe, what else is different? I've added this as a new question, please find it [here](http://stackoverflow.com/questions/38505280/freethreadeddomdocument-neutral-apartments-and-free-threaded-marshaler). – andrebroz Jul 26 '16 at 09:21