1
0

nxonce.c 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. #include "nxonce.h"
  2. #include "foundation/error.h"
  3. #if 0 && _WIN32_WINNT >= 0x600
  4. void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *param)
  5. {
  6. InitOnceExecuteOnce(once, (PINIT_ONCE_FN)init_fn, param, 0);
  7. }
  8. void NXOnceInit(nx_once_t once)
  9. {
  10. InitOnceInitialize(once);
  11. }
  12. #else
  13. /* this ONLY works because of the strict(ish) memory ordering of the AMD64/x86 processors.
  14. Don't use this implementation for a processor that has loose memory ordering restriction (e.g. ARM, PowerPC)
  15. see http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
  16. */
  17. void NXOnce(nx_once_t once, int (NX_ONCE_API *init_fn)(nx_once_t, void *, void **), void *param)
  18. {
  19. if (once->status)
  20. return;
  21. EnterCriticalSection(&once->critical_section);
  22. if (once->status)
  23. {
  24. LeaveCriticalSection(&once->critical_section);
  25. return;
  26. }
  27. init_fn(once, param, 0);
  28. // benski> not important for the x86, but on processors with weak memory-order on stores, once->status might set to 1 BEFORE all stores from init_fn complete!
  29. once->status = 1;
  30. LeaveCriticalSection(&once->critical_section);
  31. }
  32. void NXOnceInit(nx_once_t once)
  33. {
  34. once->status=0;
  35. InitializeCriticalSection(&once->critical_section);
  36. }
  37. #endif