This is a mirror of official site: http://jasper-net.blogspot.com/

Patterns for using the InitOnce functions

| Sunday, April 10, 2011
Since writing lock-free code is is such a headache-inducer, you're probably best off making some other people suffer the headaches for you. And those other people are the kernel folks, who have developed quite a few lock-free building blocks so you don't have to. For example, there's a collection of functions for manipulating interlocked lists. But today we're going to look at the one-time initialization functions.

The simplest version of the one-time initialization functions isn't actually lock-free, but it does implement the double-checked-lock pattern for you so you don't have to worry about the details. The usage pattern for the Init­Once­Execute­Once function is pretty simple. Here it is in its simplest form:

int SomeGlobalInteger;

BOOL CALLBACK ThisRunsAtMostOnce(
    PINIT_ONCE initOnce,
    PVOID Parameter,
    PVOID *Context)
{
    calculate_an_integer(&SomeGlobalInteger);
    return TRUE;
}

void InitializeThatGlobalInteger()
{
    static INIT_ONCE initOnce = INIT_ONCE_STATIC_INIT;
    InitOnceExecuteOnce(&initOnce,
                        ThisRunsAtMostOnce,
                        nullptr, nullptr);
}

In the simplest form, you give Init­Once­Execute­Once an INIT_ONCE structure (where it records its state), and a callback. If this is the first time that Init­Once­Execute­Once is called for a particular INIT_ONCE structure, it calls the callback. The callback can do whatever it likes, but presumably it's doing some one-time initialization. If another thread calls Init­Once­Execute­Once on the same INIT_ONCE structure, that other thread will wait until the first thread is finished its one-time execution.

Read more: The Old New Thing

Posted via email from Jasper-net

0 comments: