Martin Sustrik
Martin Sustrik

Reputation: 813

Equivalent of PTHREAD_MUTEX_INITIALIZER on Windows?

Is it possible to initialise CRITICAL_SECTION statically, as in pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER?

In other words, is it possible in C to initialize a global CRITICAL_SECTION inside a library without having to mess with DllMain etc.?

Upvotes: 2

Views: 1491

Answers (4)

Martin Sustrik
Martin Sustrik

Reputation: 813

The answer above from Raymond Chen solves the problem: "You can use InitOnceExecuteOnce to initialize the critical section on first use. That's what PTHREAD_MUTEX_INITIALIZER does under the covers."

note that this will work on Vista and above only --- @rkosegi

You can do it for older versions of Windows by writing your own InitOnceExecuteOnce function using InterlockedCompareExchange. --- @RaymondChen

Upvotes: 1

Chris Nauroth
Chris Nauroth

Reputation: 9844

Another possibility in earlier versions is to instruct the linker to set a pointer to your initialization function as a user-defined global initializer. There is some discussion of this here:

http://msdn.microsoft.com/en-us/library/bb918180.aspx

Here is an example:

CRITICAL_SECTION criticalSection;

static void __cdecl Initialize(void) {
    InitializeCriticalSection(&criticalSection);
}
#pragma section(".CRT$XCU", read)
__declspec(allocate(".CRT$XCU"))
const void (__cdecl *pInitialize)(void) = Initialize;

Upvotes: 1

rkosegi
rkosegi

Reputation: 14628

Yes, simply initialize in DLL_PROCESS_ATTACH and delete in DLL_PROCESS_DETACH

CRITICAL_SECTION g_cs = {0};

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            InitializeCriticalSection(&g_cs);
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
          DeleteCriticalSection(&g_cs);
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

References:

InitializeCriticalSection

DeleteCriticalSection

Upvotes: 2

Arno
Arno

Reputation: 5194

Yes! But you have to make sure that it's only done once per process. But this is typically easiest to achieve by using the DLL_PROCESS_ATTACH case of the DLLMain switch( fdwReason ) statement.

Upvotes: 1

Related Questions