Knihovna inicializace - pthread_once při provádění Win32

hlasů
4

Ahoj. Snažím se, aby se inicializační funkci plně thread-safe pro mé knihovně a já nemohl snadno najít alternativu k pthread_once, což by mělo velice snadno vyřešit tento problém. Přišel jsem do tohoto kódu:


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()Volání vede k funkci nití nebezpečné, že inicializuje knihovny.

Rád bych slyšel nějaké návrhy na to, co bych mohl dělat špatně, nebo jestli víte o lepší řešení.

Položena 10/03/2009 v 20:24
zdroj uživatelem
V jiných jazycích...                            


5 odpovědí

hlasů
0

Chtěl bych vyzkoušet tento článek. Jedná se o řešení pro C ++ singletons, ale věřím, že můžete použít řešení pro váš kód, stejně: http://www.ddj.com/cpp/199203083?pgno=1

Smutně výpis pro QLock sám chybí, vypadá to, jako kdyby se snaží prodat na CD, ale zdá se, že dost popis toho se psát sami.

Odpovězeno 10/03/2009 v 23:19
zdroj uživatelem

hlasů
2

Poté, co při pohledu na následující zdrojový kód pro pthread_once () (ze zde ) Vypadá to, že jste na správné cestě.

int pthread_once (pthread_once_t * once_control, void (* init_routine) (void))
{
    / * Zkontrolujte, zda první rychlosti * /
    if (once_control-> stav == PTHREAD_NEEDS_INIT) {
        pthread_mutex_lock (& ​​(once_control-> mutex));
        if (once_control-> stav == PTHREAD_NEEDS_INIT) {
            init_routine ();
            once_control-> stav = PTHREAD_DONE_INIT;
        }
        pthread_mutex_unlock (& ​​(once_control-> mutex));
    }
    return (OK);
}

btw, budu používat pthread_once () nahradit některé poněkud spletité funkce v mém kódu.

Odpovězeno 11/03/2009 v 03:15
zdroj uživatelem

hlasů
6

Myslím, že budete chtít použít inicializační One-Time funkce. V synchronním režimu, všechna vlákna blok do prvního závitu volání dokončí. Zdá se, že analogicky k pthread_once ().

K dispozici je ukázkový kód zde .

Takže ve vašem případě byste říci:

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
}
Odpovězeno 11/03/2009 v 03:31
zdroj uživatelem

hlasů
3

Možná budete chtít zkontrolovat, jaké pthreads-win32 dělá ve svém pthread_once () implementaion. nebo stačí použít to, že v případě, že prokáže, že je jednodušší.

Odpovězeno 22/03/2009 v 17:58
zdroj uživatelem

hlasů
2

Při použití GCC nebo řinčení, můžete použít konstruktoru a destruktor atributy. Tyto práce pro oba sdílené a statické knihovny a spustit kód před a po hlavní běží, resp. Navíc můžete zadat více konstruktoru a destruktor funkce. Mnohem čistší, než je přístup ojedinělým, a nevyžaduje, abyste si uvědomit, volat libInit () z vašeho 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");
}
Odpovězeno 12/04/2011 v 18:55
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more