diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-05 09:45:00 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-04-05 09:45:00 +0200 |
commit | b6c00dc091ec43971a78b043ed57204beba59e9b (patch) | |
tree | c44a43df6445ab0148cfdf92b69d1775fd557fbe /src | |
parent | c64f9dcd61c1ad7bef3dbf5b7647a2a2da23ac0f (diff) | |
download | lanes-b6c00dc091ec43971a78b043ed57204beba59e9b.tar.gz lanes-b6c00dc091ec43971a78b043ed57204beba59e9b.tar.bz2 lanes-b6c00dc091ec43971a78b043ed57204beba59e9b.zip |
C++ migration: one-time inits are sequenced with std::atomic_flag
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.cpp | 44 |
1 files changed, 14 insertions, 30 deletions
diff --git a/src/lanes.cpp b/src/lanes.cpp index 5fb81a3..08584a2 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -99,6 +99,8 @@ THE SOFTWARE. | |||
99 | # include <sys/types.h> | 99 | # include <sys/types.h> |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | #include <atomic> | ||
103 | |||
102 | // forwarding (will do things better later) | 104 | // forwarding (will do things better later) |
103 | static void tracking_add(Lane* lane_); | 105 | static void tracking_add(Lane* lane_); |
104 | 106 | ||
@@ -1866,7 +1868,9 @@ static void init_once_LOCKED( void) | |||
1866 | 1868 | ||
1867 | // ################################################################################################# | 1869 | // ################################################################################################# |
1868 | 1870 | ||
1869 | static volatile long s_initCount = 0; | 1871 | // we are C++20, the flags are default-initialized to 'clear' |
1872 | std::atomic_flag s_insideInit; | ||
1873 | std::atomic_flag s_initDone; | ||
1870 | 1874 | ||
1871 | // upvalue 1: module name | 1875 | // upvalue 1: module name |
1872 | // upvalue 2: module table | 1876 | // upvalue 2: module table |
@@ -1885,39 +1889,19 @@ LUAG_FUNC(configure) | |||
1885 | ** there is no problem. But if the host is multithreaded, we need to lock around the | 1889 | ** there is no problem. But if the host is multithreaded, we need to lock around the |
1886 | ** initializations. | 1890 | ** initializations. |
1887 | */ | 1891 | */ |
1888 | #if THREADAPI == THREADAPI_WINDOWS | 1892 | if (s_insideInit.test_and_set()) |
1889 | { | 1893 | { |
1890 | static volatile int /*bool*/ go_ahead; // = 0 | 1894 | // blocks until flag value is no longer the one passed in parameter |
1891 | if (InterlockedCompareExchange(&s_initCount, 1, 0) == 0) | 1895 | s_initDone.wait(false); |
1892 | { | ||
1893 | init_once_LOCKED(); | ||
1894 | go_ahead = 1; // let others pass | ||
1895 | } | ||
1896 | else | ||
1897 | { | ||
1898 | while (!go_ahead) | ||
1899 | { | ||
1900 | Sleep(1); | ||
1901 | } // changes threads | ||
1902 | } | ||
1903 | } | 1896 | } |
1904 | #else // THREADAPI == THREADAPI_PTHREAD | 1897 | else |
1905 | if (s_initCount == 0) | ||
1906 | { | 1898 | { |
1907 | static pthread_mutex_t my_lock = PTHREAD_MUTEX_INITIALIZER; | 1899 | // we are the first to enter here, because s_insideInit was false. |
1908 | pthread_mutex_lock(&my_lock); | 1900 | // and we are the only one, because it's now true. |
1909 | { | 1901 | init_once_LOCKED(); |
1910 | // Recheck now that we're within the lock | 1902 | std::ignore = s_initDone.test_and_set(); |
1911 | // | 1903 | s_initDone.notify_all(); |
1912 | if (s_initCount == 0) | ||
1913 | { | ||
1914 | init_once_LOCKED(); | ||
1915 | s_initCount = 1; | ||
1916 | } | ||
1917 | } | ||
1918 | pthread_mutex_unlock(&my_lock); | ||
1919 | } | 1904 | } |
1920 | #endif // THREADAPI == THREADAPI_PTHREAD | ||
1921 | 1905 | ||
1922 | STACK_GROW(L, 4); | 1906 | STACK_GROW(L, 4); |
1923 | STACK_CHECK_START_ABS(L, 1); // settings | 1907 | STACK_CHECK_START_ABS(L, 1); // settings |