I get access to the IAudioEndpointVolume interface in the main worker thread of a service like this (error checks omitted):
CoInitialize(NULL);
CoCreateGuid(&g_guidMyContext);
CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, IID_IMMDeviceEnumerator, (void**)&m_pEnumerator);
IMMDevice *pEndpoint = NULL;
m_pEnumerator->GetDevice(&deviceID[0], &pEndpoint);
IAudioEndpointVolume *pAudioVol = NULL;
pEndpoint->Activate(__uuidof(IAudioEndpointVolume), CLSCTX_ALL, NULL, (void**)&pAudioVol);
CAudioEndpointVolumeCallback *pVolumeCallback = new CAudioEndpointVolumeCallback(pAudioVol, 100, TRUE, m_debugLog, m_logMutex);
The CAudioEndpointVolumeCallback class then stores the IAudioEndpointVolume pointer in a member variable and calls RegisterControlChangeNotify(this) on it in its constructor.
This class may also start a thread to smoothly change the volume from one value to another over a short time period. So at the end I make calls to the IAudioEndpointVolume interface from different threads. In general all of this works as intended, but I am experiencing some strange behavior in some edge cases. When checking the code again I stumbled across the comments about threading in the MSDN documentation (I don't have any prior experience with COM objects) and wondered if what I am doing is correct.
So, is it safe to make calls to the IAudioEndpointVolume interface from different threads with the code above? Do I have to protect those calls with a mutex?
I am a bit confused and am not sure if I really understood the behavior of the COM Threading Models.
CoInitialize(NULL) initializes single threaded apartment (STA) and interface pointers you have there are only [supposed to be] valid on this thread only. You can pass them to another thread through GIT, or by CoMarshalInterThreadInterfaceInStream on this thread and getting a "duplicate" of it back with CoGetInterfaceAndReleaseStream on the target thread, where you are going to use it.
Depending on implementation behind the interface pointer in question you might eventually obtain the same pointer (in which case the whole trick would be equal to simply using the pointer on another thread), however this is not safe in general case.
Another option is to use MTA (as opposed to STA) and then you are allowed to pass pointers directly among all/any MTA threads.
Related
This is triggered by another question.
Specifically, I have a in process COM class, that is defined in the CLSID registry as having a ThreadingModel of Both.
Our process activates this object through CoCreateInstance (not CoCreateInstanceEx, if that even matters for an in-proc dll server)
Given a threading model of Bothand given th rules listed in the docs:
Threading model of server | Apartment server is run in
------------------------------------------------------
Both | Same apartment as client
and given what Hans writes in the other answer:
... Marshaling occurs when the client call needs to be made on a
different thread. ... can happen when the ThreadingModel specified in
the comClass element demands it. In other words, when the COM object
was created on one thread but is called on another and the server is
not thread-safe.
my tentative conclusion would be that such an object will never need implicit marshalling of calls to its interfaces, since the object will always live in the same apartment as its client.
Is that correct, even if the client process is running as STA?
Yes, there may be marshaling.
If the client of your COM class is running in an STA and you attempt to invoke your class from another apartment, it will have to marshal to the apartment that it was created in.
The COM terminology can be really confusing. When you refer to a 'client' in this case, you're really referring to a thread, not the entire application (as it would imply).
Both just means that the threading model of the server conforms to the client that instantiates it. That is, when you instantiate your class, it takes on the threading model of the thread it was created on. Since you're instantiating the server in an STA, your server will use STA, meaning it can only be invoked on the thread that created it; if another thread tries to invoke it, it will marshal to the thread it was created on.
I can't help myself posting this, although it is not a direct answer to the question.
There's a brilliant MSKB article from the golden ages of COM: INFO: Descriptions and Workings of OLE Threading Models. Still there, and has all the relevant info. The point is, you should not worry about whether there is marshaling or not, if you follow the rules. Just register your object as ThreadingModel=Both, aggregate the Free-Threaded Marshaler with CoCreateFreeThreadedMarshaler, and be done. COM will do the marshaling if needed, in the best possible way. Depending on the client's apartment model, the client code may receive the direct pointer to your interface, if it follows the rules too.
Any "alien" interface that you may receive when a method of your interface gets called, will be valid in the scope of the call, because you stay on the same thread. If you don't need to store it, that's all that matters.
If however you do need to cache the "alien" interface, the right way of doing this would be to store it using CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStream:
To store it:
Enter critical section;
call CoMarshalInterThreadInterfaceInStream and store the IStream pointer in a member field;
Leave critical section;
To retrieve it
Enter critical section;
call CoGetInterfaceAndReleaseStream to retrieve the interface
call CoMarshalInterThreadInterfaceInStream and store it again as IStream for any future use
Leave critical section;
Use the interface in the scope of the current call
To release it:
When you no longer need keeping it, just release the stored IStream (inside the critical section).
If the "alien" object is free-threaded too, and the things are happening inside the same process, you will likely be dealing with a direct interface pointer after CoGetInterfaceAndReleaseStream. However, you should not make any assumptions, and you really don't need to know if the object your dealing with is the original object or a COM marshaller proxy.
This can be slightly optimized by using CoMarshalInterface w/ MSHLFLAGS_TABLESTRONG / CoUnmarshalInterface / IStream::Seek(0, 0) / CoReleaseMarshalData instead of CoGetInterfaceAndReleaseStream/CoGetInterfaceAndReleaseStream, to unmarshal the same interface as many times as needed without releasing the stream.
More complex (and possibly more efficient) caching scenarios are possible, involving Thread Local Storage. However, I believe that would be an overkill. I did not do any timing, but I think the overhead of CoMarshalInterThreadInterfaceInStream/CoGetInterfaceAndReleaseStreamis really low.
That said, if you need to maintain a state that stores any resources or objects which may require thread affinity, other than aforementioned COM interfaces, you should not mark your object as ThreadingModel=Both or aggregate the FTM.
Yes, marshalling is still possible. A couple of examples:
the object is instantiated from an MTA thread and so placed into an MTA apartment and then its pointer is passed into any STA thread and that STA thread calls methods of the object. In this case an STA thread can only access the object via marshalling.
the object is instantiated from an STA thread and so placed into an STA apartment belonging to that thread and then its pointer is passed into another STA thread or an MTA thread. In both cases those threads can only access the object via marshalling.
In fact you can expect no marshalling only in the following two cases:
the object is instantiated from an MTA thread and then only accessed by MTA threads - both the one that instantiated the object and all other MTA threads of the same process.
the object is instantiated from an STA thread and then only accessed by that very thread
and in all other cases marshalling will kick in.
ThreadingModel = Both simply means that the COM server author can give a guarantee that his code is thread-safe but cannot give the same guarantee that other code he didn't write will be called in a thread-safe way. The most common case of getting such foreign code to execute is through callbacks, connection points being the most common example (usually called "events" in client runtimes).
So if the server instance was created in an STA then the client programmer is going to expect the events to run on that same thread. Even if a server method that fires such an event was called from another thread. That requires that call to be marshaled.
I open Matlab engine in an initialization thread, doing :
bool MY_MATLAB_ENGINE_o::Open()
{
// Handle the case where engine is already open
if( MatlabEngine )
{
return true;
}
else if( !( MatlabEngine = engOpen( 0 ) ) )
{
return false;
}
IsEngineOpen.SetValue( true );
return true;
}
Function engOpen() opens a COM channel to Matlab.
Once the engine is open, the thread falls in wait event mode.
Then, in another thread, I do this :
bool MY_MATLAB_ENGINE_o::ChangeDirectory( QString strPath )
{
QString strPathToScript = "cd('" + strPath + "');";
QByteArray ba = strPathToScript.toLatin1();
const char* cPathToScript = ba.data();
if( MatlabEngine )
{
engEvalString( MatlabEngine, cPathToScript );
return true;
}
return false;
}
I get a CoInitialize has not been called first-chance exception on engEvalString( MatlabEngine, cPathToScript ); which seems to tell me that Matlab COM server isn't available (but Matlab engine is still up and running).
When I put everything in the same thread it works fine though, but that's not the kind of design I had in mind.
I find Matlab engine documentation lack information about engine+COM. Any idea how to have engine initialization and function calls in separated threads ?
Thanks !
EDIT following RobH's answer
I added this method to my class (instantiated in the second thread) :
bool MY_MATLAB_FUNCTION_CALL_o::PostThreadCreationHook()
{
HRESULT hr;
hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr))
{
return false;
}
return true;
}
And now when I call engEvalString( MatlabEngine, cPathToScript ); I get The application called an interface that was marshalled for a different thread first-chance exception :) I have so much fun this morning ! :)
So, CoMarshalInterface() ?
CoInitialize has to be called from every thread where you use a COM object, not just the main thread.
It has been a decade since I last automated Matlab, so excuse rustiness in what follows. That you have received the CoInitialize error suggests that the engOpen call wraps underlying COM calls. Unfortunately, this exposes you unawares to the can of worms that is COM. I guess you are right and that engOpen includes a call to CoInitialize, which initialises the COM library on the current thread. To access COM objects from a thread CoInitialize must always have been called on that thread before any calls to COM (other than one permitted COM function, I forget which.)
My advice is to isolate all of your Matlab calls onto one thread now. If you do that you won't have to make the explicit CoInitialize call, and you avoid any later multithreaded COM issues. You might get your program working today by calling CoInitialize on the second thread but one day you'll be bitten by another COM problem.
[I spent about a decade elbows-deep on COM and it is full of bear traps. You could spend a few weeks reading up on a technology which Microsoft tried to hide / kill with .Net, but it is better just to take the easy (single-thread) path now and forget about it.]
Update
I'm afraid your edit has tripped you into the mire of COM threading models. COINIT_MULTITHREADED effectively tells COM that you're going to take care of all of the little nuances of threading, which is almost certainly not what you want to do. COM operates with several (last time I paid attention it was three) threading models and the parameter you pass to CoInitializeEx declares which of those models you wish to use.
Apologies to all if what follows is slightly off.
If you specify COINIT_MULTITHREADED you need to either know that the COM object you are calling is thread-safe or do the appropriate locking (and marshalling of interfaces and data between threads) yourself.
COINIT_APARTMENTTHREADED, which is probably what engOpen uses as in my experience it's the most common, lets the COM library deal with multithreading for you. The library may, for instance, create proxy and stub objects to mediate calls across threads (or process boundaries, which is what will happen when you call to Matlab.)
engOpen created a Matlab proxy object on your main thread. This proxy object can be called from the thread where it was created and, if I recall correctly, from any other thread in the 'apartment' (where CoInitializeEx has been called with COINIT_APARTMENTTHREADED.) You have tried to call through the proxy from a thread in a different threading model, the COM library has noticed, and has issued the error you mention.
In many ways COM is amazing, but the intricacies are a pain in the arse. Be thankful you are never likely to have to use Distributed COM, which is truly nasty!
Update 2
My ancient memory of COM threading models is wrong. This MSDN page states that there is one thread per apartment with COINIT_APARTMENTTHREADED. COM objects can be accessed using the same interface pointer from all threads in the apartment where they were created. For COINIT_APARTMENTTHREADED that means just the thread where the object was created. In COINIT_MULTITHREADED that would be all the threads in the multithreaded apartment but (1) you don't get to choose which thread the Matlab engine is created on if you use engOpen and (2) trying to call a COM object that you didn't write from a multithreaded apartment is risky. The original OLE threading model only allowed COM calls from the main GUI thread, BTW.
I'm maintaining an application which uses Windows Explorer overlay icons. Occasionally some operations require me to forcibly refresh explorers view for a particular folder. I do so using the following function which uses COM:
void RefreshExplorerView(CString strPath)
{
CComPtr<IShellWindows> pShellWindows;
CoInitialize(NULL);
if(SUCCEEDED(pShellWindows.CoCreateInstance(CLSID_ShellWindows)))
{
IDispatch* pFolder=NULL;
VARIANT variant;
V_VT(&variant) = VT_I4;
for(V_I4(&variant) = 0; pShellWindows->Item(variant, &pFolder) == S_OK; V_I4(&variant)++)
{
CComPtr<IWebBrowserApp> pWebBrowserApp;
if(SUCCEEDED(pFolder->QueryInterface(IID_PPV_ARGS(&pWebBrowserApp))))
{
BSTR LocationURL = NULL;
pWebBrowserApp->get_LocationURL(&LocationURL);
if(LocationURL != NULL && strPath.CompareNoCase(LocationURL) == 0)
{
CComPtr<IServiceProvider> pServiceProvider;
if(SUCCEEDED(pWebBrowserApp->QueryInterface(IID_PPV_ARGS(&pServiceProvider))))
{
CComPtr<IShellBrowser> pShellBrowser;
if(SUCCEEDED(pServiceProvider->QueryInterface(IID_PPV_ARGS(&pShellBrowser))))
{
IShellView* pShellView;
if(SUCCEEDED(pShellBrowser->QueryActiveShellView(&pShellView)))
{
pShellView->Refresh();
pShellView->Release();
}
}
}
}
SysFreeString(LocationURL);
}
pFolder->Release();
pFolder = NULL;
}
}
CoUninitialize();
}
I've noticed that when my program does this refresh regularly it slowly grows in size and UMDH has shown me that I appear to be leaking pFolder and pShellWindow instances every time this runs. I can't work out why on earth this happens since as far as I can tell these are released properly. Can anyone see what I'm missing?
You release pShellWindows after CoUninitialize, which is incorrect.
The rest of interfaces seem to be released fine. Note that you could improve cleanless and readability greatly by using CComQIPtr instead of QueryInterface, and not using raw pointers at all (BSTR, IFoo*) and replace them with smart auto-releasing wrappers.
pFolder might be leaking too, if Item call is successful but returns code other than S_OK. Again, use of CComPtr<IFolder> instead of IFolder* would immediately resolve this problem without even drawing any attention to it.
CoInitialize(NULL);
There's more than one problem with this statement. #Roman explained how you can leak by uninitializing too soon. But this will also go bad in more than one way, the apartment state of a thread is a Really Big Deal in COM:
You are not checking the return value of CoInitialize(). This will blow up the client app that calls this function if it has already called CoInitializeEx() and selected MTA instead of STA. That will make CoInitialize() fail, you cannot change the thread state after it was committed. Your CoUninitialize() call will blow the client app to smithereens, making all of its subsequent COM calls fail.
Selecting STA also requires that you implement the contract for a single threaded apartment. Which states that you never block the thread, you're okay with that. And that you pump a message loop. The message loop is crucial to marshaling calls to the single-threaded apartment. You are not okay with that, nor can you reasonably ensure that this is taken care of in a function like this. Particularly important for the shell interfaces, the vast majority of them are not thread-safe. The consequence of not pumping is deadlock. You may get away with not pumping, it is not a guaranteed deadlock. You'll get a bit of leeway here since these are probably out-of-process interfaces.
Particularly the last requirement can only be met by the code that created the thread that calls this function, only it is in control over what the thread does beyond calling your function. If you cannot get the guarantee that the client app initializes COM correctly then the only truly safe thing to do is to create a thread yourself.
In Microsoft Visual C++ I can call CreateThread() to create a thread by starting a function with one void * parameter. I pass a pointer to a struct as that parameter, and I see a lot of other people do that as well.
My question is if I am passing a pointer to my struct how do I know if the structure members have been actually written to memory before CreateThread() was called? Is there any guarantee they won't be just cached? For example:
struct bigapple { string color; int count; } apple;
apple.count = 1;
apple.color = "red";
hThread = CreateThread( NULL, 0, myfunction, &apple, 0, NULL );
DWORD WINAPI myfunction( void *param )
{
struct bigapple *myapple = (struct bigapple *)param;
// how do I know that apple's struct was actually written to memory before CreateThread?
cout << "Apple count: " << myapple->count << endl;
}
This afternoon while I was reading I saw a lot of Windows code on this website and others that passes in data that is not volatile to a thread, and there doesn't seem to be any memory barrier or anything else. I know C++ or at least older revisions are not "thread aware" so I'm wondering if maybe there's some other reason. My guess would be the compiler sees that I've passed a pointer &apple in a call to CreateThread() so it knows to write out members of apple before the call.
Thanks
No. The relevant Win32 thread functions all take care of the necessary memory barriers. All writes prior to CreateThread are visible to the new thread. Obviously the reads in that newly created thread cannot be reordered before the call to CreateThread.
volatile would not add any extra useful constraints on the compiler, and merely slow down the code. In practice thiw wouldn't be noticeable compared to the cost of creating a new thread, though.
No, it should not be volatile. At the same time you are pointing at the valid issue. Detailed operation of the cache is described in the Intel/ARM/etc papers.
Nevertheless you can safely assume that the data WILL BE WRITTEN. Otherwise too many things will be broken. Several decades of experience tell that this is so.
If thread scheduler will start thread on the same core, the state of the cache will be fine, otherwise, if not, kernel will flush the cache. Otherwise, nothing will work.
Never use volatile for interaction between threads. It is an instruction on how to handle data inside the thread only (use a register copy or always reread, etc).
First, I think optimizer cannot change the order at expense of the correctness. CreateThread() is a function, parameter binidng for function calls happens before the call is made.
Secondly, volatile is not very helpful for the purpose you intend. Check out this article.
You're struggling into a non-problem, and are creating at least other two...
Don't worry about the parameter given to CreateThread: if they exist at the time the thread is created they exist until CreateThread returns. And since the thread who creates them does not destroy them, they are also available to the other thread.
The problem now becomes who and when they will be destroyed: You create them with new so they will exist until a delete is called (or until the process terminates: good memory leak!)
The process terminate when its main thread terminate (and all other threads will also be terminated as well by the OS!). And there is nothing in your main that makes it to wait for the other thread to complete.
Beware when using low level API like CreateThread form languages that have thir own library also interfaced with thread. The C-runtime has _beginthreadex. It call CreateThread and perform also other initialization task for the C++ library you will otherwise miss. Some C (and C++) library function may not work properly without those initializations, that are also required to properly free the runtime resources at termination. Unsing CreateThread is like using malloc in a context where delete is then used to cleanup.
The proper main thread bnehavior should be
// create the data
// create the other thread
// // perform othe task
// wait for the oter thread to terminate
// destroy the data
What the win32 API documentation don't say clearly is that every HANDLE is waitable, and become signaled when the associate resource is freed.
To wait for the other thread termination, you main thread will just have to call
WaitForSingleObject(hthread,INFINITE);
So the main thread will be more properly:
{
data* pdata = new data;
HANDLE hthread = (HANDLE)_beginthreadex(0,0,yourprocedure, pdata,0,0);
WaitForSingleObject(htread,INFINITE);
delete pdata;
}
or even
{
data d;
HANDLE hthread = (HANDLE)_beginthreadex(0,0,yourprocedure, &d,0,0);
WaitForSingleObject(htread,INFINITE);
}
I think the question is valid in another context.
As others have pointed out using a struct and the contents is safe (although access to the data should by synchronized).
However I think that the question is valid if you hav an atomic variable (or a pointer to one) that can be changed outside the thread. My opinion in that case would be that volatile should be used in this case.
Edit:
I think the examples on the wiki page are a good explanation http://en.wikipedia.org/wiki/Volatile_variable
I have created an in-process COM object (DLL) using ATL. Note that this is an object and not a control (so has no window or user-interface.) My problem is that I am trying to fire an event from a second thread and I am getting a 'Catastrophic failure' (0x8000FFFF). If I fire the event from my main thread, then I don't get the error. The second thread is calling CoInitializeEx but this makes no difference. I am using the Apartment threading model but switching to Free Threaded doesn't help.
The fact I am trying to do this from a second thread is obviously crucial. Is there an easy way to do this or am I going to have to implement some hidden-window form of messaging?
For example, in my main object's source file:
STDMETHODIMP MyObject::SomeMethod(...)
{
CreateThread(NULL, 0, ThreadProc, this, 0, NULL);
// Succeeds with S_OK
FireEvent(L"Hello, world!");
return S_OK;
}
DWORD WINAPI ThreadProc(LPVOID param)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
MyObject* comObject = reinterpret_cast<MyObject*>(param);
// Fails with 0x8000FFFF
comObject->FireEvent(L"Hello, world!");
}
void MyObject::FireEvent(BSTR str)
{
...
// Returns 0x8000FFFF if called from ThreadProc
// Returns S_OK if called from SomeMethod
pConnection->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, ¶ms, NULL, NULL, NULL);
}
COM basics
In STA your object lives on a single thread (The Thread). This thread is the one it's created on, it's methods are executed on and it's events are fire on. The STA makes sure that no two methods of your object are executed simultaneously (because they have to be executed on The Thread so this is a nice consequence).
This does not mean that your object can't be accessed from other threads. This is done by creating proxies of your object for every thread other than The Thread. On The Thread you pack an IUnknown with CoMarshalInterThreadInterfaceInStream and on the other thread you unpack with CoGetInterfaceAndReleaseStream which actually creates the proxy on the other thread. This proxy uses the message pump to sync calls to you object, calls that are still executed on The Thread, so The Thread has to be free (not busy) to executed a call from another thread.
In your case you want your object to be able to execute methods on one thread and rise events on another thread. So this has to happen in MTA, so your object has to live in MTA, so your class has to be free-threaded. Threads belong to exactly one apartment, so a thread can not be in MTA and STA simultaneously. If your object lives in MTA whenever an STA object tries to use it, it will have to create a proxy. So you get a slight overhead.
What I guess is that you are thinking of some very clever "technique" to offload your main thread, and do some "async" events, which will not fly in the end :-)) If you think about it there has to a listener on this second [worker] thread...
Btw, this line
MyObject* comObject = reinterpret_cast<MyObject*>(param);
can be done in MTA only.
I think the real problem is not what your component is configured with, but the host process. Many hosts, like the Office Object Model ones, live in a single threaded apartment in which case it is not allowed to call them from anything but the main thread.
If that is the case you can let COM do the work by using the single threaded apartment model and moving the actual call to a function in a CoClass and invoke that function from your thread.
That only passes window messages behind the scenes as well, but spares you from implementing this yourself.
Threading in COM (wikipedia):
The Single-Threaded Apartment (STA) model is a very commonly used model. Here, a COM object stands in a position similar to a desktop application's user interface. In an STA model, a single thread is dedicated to drive an object's methods, i.e. a single thread is always used to execute the methods of the object. In such an arrangement, method calls from threads outside of the apartment are marshalled and automatically queued by the system (via a standard Windows message queue). Thus, there is no worry about race conditions or lack of synchronicity because each method call of an object is always executed to completion before another is invoked.
See also Message Pumping in the same article.