c - Skal jeg tilføje synkronisering til denne kode?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg skriver nogle kode for at udføre eksplicit link til en DLL. Denne kode tilbydes mine brugere som et alternativ til implicit at forbinde med en .lib-fil. I øjeblikket ser min planlagte kode sådan ud:


void DisableModule(int Module)
{
    typedef void (*DisableModuleProc)(int);
    static DisableModuleProc proc = NULL;
    if (proc == NULL)
        proc = (DisableModuleProc)GetProcAddress(hModule, "DisableModule");
    proc(Module);
}


Der er mange funktioner i denne formular, og jeg har ekskluderet fejlkontrollen for formålet med dette spørgsmål.


Mit problem vedrører trådsikkerhed. Denne funktion kan potentielt kaldes samtidigt fra flere tråde. Det er klart, at der er et løb på den statiske variabel \_DisableModule. Min tro er, at fordi \_DisableModule vil blive justeret på maskinordgrænse (enten 32 eller 64 bit grænse afhængigt af mål), at der ikke kan opstå rive, og så er løbet god. Det er muligt at GetProcAddress vil blive kaldt flere gange end nødvendigt, men jeg tror ikke på, at det berører programmets rigtighed.


Er min analyse korrekt?

Bedste reference


Denne kode er helt sikker på x86 og amd64.
I værste fald kaldes GetProcAddress flere gange.


På andre arkitekturer kan der være problemer med, at delvis skrivning afbrydes. For at omgå dette kan du bruge atom (InterlockedComparExchange ...), men det er overflødigt her.

Andre referencer 1


En simpel lås skal gøre det.

Du bør kun tage låsen hvis proc==NULL, så efter et stykke tid vil det aldrig blive taget. Så sagen er ikke et problem.

Du kan ringe GetProcAddress med låsen holdt eller uden den.



Mulighed 1:


if (proc == NULL) {
    lock();
    proc = (DisableModuleProc)GetProcAddress(hModule, "DisableModule");
    unlock();
}


valgmulighed 2:


if (proc == NULL) {
    DisableModuleProc tmp = (DisableModuleProc)GetProcAddress(hModule, "DisableModule");
    lock();
    if (proc == NULL) {
        proc = tmp;
    } else {
        // Any free needed?
    }
    unlock();
}