Library Initialization - pthread_once in Win32 Implementation

Hello. I am trying to make a fully thread safe initialization function for my library, and I could not easily find an alternative to pthread_once, which should solve the problem very easily. I came to this code:

void libInit (void) { #ifdef WIN32 static volatile int initialized = 0; static HANDLE mtx; if (!initialized) { if (!mtx) { HANDLE mymtx; mymtx = CreateMutex(NULL, 0, NULL); if (InterlockedCompareExchangePointer(&mtx, mymtx, NULL) != NULL) CloseHandle(mymtx); } WaitForSingleObject(mtx); if (!initialized) { libInitInternal(); initialized = 1; } ReleaseMutex(mtx); } #else static pthread_once_t initialized = PTHREAD_ONCE_INIT; pthread_once(&initialized, libInitInternal); #endif } 

A call to libInitInternal() results in an unsafe function that initializes the library.

I would love to hear any suggestions on what I might do wrong, or you know about a better solution.

+4
source share
5 answers

I think you want to use the One-Time Initialization functionality. In synchronous mode, all threads are blocked until the first thread causes it to terminate. Seems similar to pthread_once ().

Here is a sample code .

So, in your case, you would say:

 BOOL CALLBACK CallLibInitInternal(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) { libInitInternal(); return TRUE; } void libInit() { #ifdef WIN32 static INIT_ONCE s_init_once; InitOnceExecuteOnce(&s_init_once, CallLibInitInternal, NULL, NULL); #else ... #endif } 
+6
source

You might want to check what pthreads-win32 does in pthread_once () . or just use it if it is easier.

+3
source

Looking at the following pthread_once () source code (from here ), it looks like you are "On the right track."

  int pthread_once (pthread_once_t * once_control, void (* init_routine) (void))
 {
     / * Check first for speed * /
     if (once_control-> state == PTHREAD_NEEDS_INIT) {
         pthread_mutex_lock (& ​​(once_control-> mutex));
         if (once_control-> state == PTHREAD_NEEDS_INIT) {
             init_routine ();
             once_control-> state = PTHREAD_DONE_INIT;
         }
         pthread_mutex_unlock (& ​​(once_control-> mutex));
     }
     return (OK);
 }

btw, I will use pthread_once () to replace some rather confusing functions in my code.

+2
source

When using GCC or clang, you can use the attributes of the constructor and destructor. These works for both general and static libraries, as well as for code execution before and after main, are performed accordingly. In addition, you can specify several constructor and destructor functions. Much cleaner than a singleton approach, and doesn't require you to forget to call libInit () from your main ().

 static void __attribute__((constructor)) your_lib_init(void) { fprintf(stderr, "library init\n"); } static void __attribute__((destructor)) vensim_ctx_destroy(void) { fprintf(stderr, "library destroy\n"); } 
+2
source

I would review this article. This solution is for C ++ singleton, but I believe that you can also use the solution for your code: http://www.ddj.com/cpp/199203083?pgno=1

Unfortunately, the listing of QLock itself is missing, it seems that they are trying to sell the CD, but it seems that it is enough to describe it to write it yourself.

0
source

All Articles