2009-03-10 15 views
4

Hello. Kitaplığım için tam olarak güvenli bir başlatma işlevi yapmaya çalışıyorum ve pthread_once'a kolayca çözüm bulamayan bir alternatif bulamadım. Bu kod geldiniz:Kitaplık başlatması - Win32 uygulamasında pthread_once


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 
} 

libInitInternal() çağrı kütüphane başlatır bir iş parçacığı güvenli olmayan fonksiyonu yol açar.

Neyi yanlış yaptığımı veya daha iyi bir çözüm olup olmadığını öğrenmek için herhangi bir öneri duymak isterim.

+0

Bu bir statik kitaplık veya dll mi? – grieve

+0

Bu bir DLL değil. DLL'ler için bir başlatma işlevi olduğunu biliyorum ama istediğim bu değil. –

cevap

0

Bu makaleye bakardım. Bu, C++ singletons için bir çözümdür, ancak kodunuz için de çözümü kullanabileceğinize inanıyorum: http://www.ddj.com/cpp/199203083?pgno=1

Ne yazık ki, QLock'un kendisinin listesi eksiktir, CD'yi satmaya çalışıyormuş gibi görünür, ancak Kendinizi yazmak için yeterli açıklama var gibi görünüyor.

2

pthread_once() (here'den itibaren) için aşağıdaki kaynak koduna baktıktan sonra Doğru yoldasınız gibi görünüyor.

 
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, benim kodunda bazı oldukça dolambaçlı fonksiyonlarını yerine pthread_once() kullanarak olacak.

+2

Çift Kontrollü Kilitleme antipattern değil mi? Portably çalışmaması gerekiyordu. Platformumda/platformun üzerinde yoğun bir şekilde test edilmeden bunu kullanmamalıydım ... S. Meyers ve A. Alexandrescu'nun şu makalesine bakınız: http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised. pdf – paercebal

6

One-Time Initialization işlevini kullanmak istediğinizi düşünüyorum. Senkron modda, tüm iş parçacıkları, çağrılacak ilk iş parçacığı tamamlanana kadar engellenir. Pthread_once() ile benzer görünüyor.

sample code here var.

yüzden durumda, derdi:

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 
} 
+1

Bu, yalnızca Windows Vista ve daha yeni sürümlerde kullanılabilir. Windows 98 üzerinde çalışacak bir şey olmasını isterdim. –

+0

Gerçekten mi? Dokümanlarda bunu çok özledim. Afedersiniz. Kodu yazmanız gerekecek ve OP'niz yakın görünüyor. Muhtemelen herkesin beklediği, aynı nesnede beklediği, adlandırılmış bir nesne oluşturmak ister. –

2

GCC veya clang kullanırken, kurucu ve yıkıcı niteliklerini kullanabilirsiniz. Bunlar hem paylaşılan hem de statik kütüphaneler için çalışır ve ana ve daha sonra kod çalıştırılır. Ayrıca, birden fazla kurucu ve yıkıcı işlevini de belirtebilirsiniz. Singleton yaklaşımından çok daha temizdir ve main() 'dan libInit()' i çağırmayı hatırlamanızı gerektirmez.

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"); 
} 
+0

Bu standart değil, bu yüzden diğer derleyiciler için düzenli "singleton yaklaşımı" tarafından yedeklenmesi gerekirdi. Gerçi, gerçekten iyi görünüyor. Yapabilseydim, ben +1. –