Search code examples
c++multithreadingcommarshallingapartments

To Marshal or Not to Marshal


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?


Solution

  • 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.