/* Implement a function wrapper to guarantee initialization *thread-safetyforlibrarysingletons. * *NOTE:Thesefunctionsusestaticlocks,andcanonlybe *usedwithonecommonargumentpercompilationunit.So * *file1.c: *vpx_once(foo); *... *vpx_once(foo); * *file2.c: *vpx_once(bar); * *willensurefoo()andbar()areeachcalledonlyonce,butin * *file1.c: *vpx_once(foo); *vpx_once(bar): * *bar()willneverbecalledbecausethelockisusedup *bythecalltofoo().
*/
#if CONFIG_MULTITHREAD && defined(_WIN32) #include <windows.h> #include <stdlib.h> /* Declare a per-compilation-unit state variable to track the progress *ofcallingfunc()onlyonce.Thismustbeatglobalscopebecause *localinitializersarenotthread-safeinMSVCpriortoVisual *Studio2015. * *Asastatic,once_statewillbezero-initializedasprogramstart.
*/ staticLONG once_state; staticvoid once(void (*func)(void)) { /* Try to advance once_state from its initial value of 0 to 1. *Onlyonethreadcansucceedindoingso.
*/ if (InterlockedCompareExchange(&once_state, 1, 0) == 0) { /* We're the winning thread, having set once_state to 1.
* Call our function. */
func(); /* Now advance once_state to 2, unblocking any other threads. */
InterlockedIncrement(&once_state); return;
}
/* We weren't the winning thread, but we want to block on *thestatevariablesowedon'treturnbeforefunc() *hasfinishedexecutingelsewhere. * *Trytoadvanceonce_statefrom2to2,whichisonlypossible *afterthewinningtheadadvancesitfrom1to2.
*/ while (InterlockedCompareExchange(&once_state, 2, 2) != 2) { /* State isn't yet 2. Try again. * *Weareusedforsingletoninitializationfunctions, *whichshouldcompletequickly.Contentionwilllikewise *berare,soit'sworthwhiletouseasimplebutcpu- *intensivebusy-waitinsteadofsuccessivebackoff, *waitingonakernelobject,oranotherheavier-weightscheme. * *Wecanatleastyieldourtimeslice.
*/
Sleep(0);
}
/* We've seen once_state advance to 2, so we know func() *hasbeencalled.Andwe'veleftonce_stateaswefoundit, *sootherthreadswillhavethesameexperience. * *It'ssafetoreturnnow.
*/ return;
}
#else /* No-op version that performs no synchronization. *_rtcd() is idempotent, *soaslongasyourplatformprovidesatomicloads/storesofpointers *nosynchronizationisstrictlynecessary.
*/
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.