Search code examples
windowscomatlcom-server

Is Windows Com Server with multiple clients connected multi threaded?


I have a com server that is started in the following way:

extern "C" int WINAPI _tWinMain(HINSTANCE hInstance, 
    HINSTANCE /*hPrevInstance*/, LPTSTR lpCmdLine, int /*nShowCmd*/)
{
    lpCmdLine = GetCommandLine(); //this line necessary for _ATL_MIN_CRT

#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
    HRESULT hRes = CoInitializeEx(NULL, COINIT_MULTITHREADED);
#else
    HRESULT hRes = CoInitialize(NULL);
#endif
    _ASSERTE(SUCCEEDED(hRes));
    _Module.Init(ObjectMap, hInstance, &LIBID_EXACTACONSOLIDATIONLib);
    _Module.dwThreadID = GetCurrentThreadId();
    TCHAR szTokens[] = _T("-/");

    int nRet = 0;
    BOOL bRun = TRUE;
    LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
    while (lpszToken != NULL)
    {
        if (lstrcmpi(lpszToken, _T("UnregServer"))==0)
        {
            _Module.UpdateRegistryFromResource(IDR_ExactaConsolidation, FALSE);
            nRet = _Module.UnregisterServer(TRUE);
            bRun = FALSE;
            break;
        }

        if (lstrcmpi(lpszToken, _T("RegServer"))==0)
        {
            _Module.UpdateRegistryFromResource(IDR_ExactaConsolidation, TRUE);
            nRet = _Module.RegisterServer(TRUE);
            bRun = FALSE;
            break;
        }

        lpszToken = FindOneOf(lpszToken, szTokens);
    }
    if (bRun)
    {
        _Module.StartMonitor();

        #if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)

        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, 
            REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
        _ASSERTE(SUCCEEDED(hRes));
        hRes = CoResumeClassObjects();

        #else

        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, 
            REGCLS_MULTIPLEUSE);

        #endif

        _ASSERTE(SUCCEEDED(hRes));

        MSG msg;
        while (GetMessage(&msg, 0, 0, 0))
            DispatchMessage(&msg);

        _Module.RevokeClassObjects();
        Sleep(dwPause); //wait for any threads to finish
    }
}

My question is if multiple clients are connected to this COM Server does it process the requests (function calls to the com object that the com server is hosting) in a synchronous fashion?

The reason I ask is because of the following scenario: Client A and Client B both connect to Com Server C. They both issue a request and this request involves using the COM Object to retrieve the next item (order in my case) from the database. No two clients should be allowed to have the same item so what basically happens is each item is marked as taken when it's retrieved from the database and returned to the client.

Is it sufficient in the scenario above to mark the item in the database as taken without worrying about race conditions if it's 2 clients connecting to the same COM server? If the requests are processed synchronously I would think this would be ok to just mark the item as taken.


Solution

  • This depends on whether the thread registering (or, rather, creating) the class objects is a Single Threaded Apartment or Multi-Threaded Apartment. See the MSDN article on the threading modes. If you initialized COM with CoInitialize(NULL) or CoInitializeEx(NULL, COINIT_APARTMENTTHREADED), you're in a STA; if you used CoInitializeEx(NULL, COINIT_MULTITHREADED) or CoInitializeEx(NULL, 0), you're in a MTA.

    If you're in a MTA, COM will make multiple calls to your objects at the same time from a thread pool. In a STA, only one call will be made at a time. If you just want to avoid races, using a STA can be a reasonable approach; keep in mind that this will create a performance bottleneck, however, so for very high volume servers, or servers where requests may take a while, using a MTA with your own synchronization logic may be preferable.