blob: 0618395b737f9759bc099097b2c8b387263ec079 [file] [log] [blame]
brians2fdfc072013-02-26 05:35:15 +00001#ifdef __VXWORKS__
2#include <taskLib.h>
3#else
4#include <sched.h>
5#endif
6
7#include "aos/common/type_traits.h"
8
9// It doesn't use pthread_once, because Brian looked at the pthreads
10// implementation for vxworks and noticed that it is completely and entirely
11// broken for doing just about anything (including its pthread_once). It has the
Brian Silverman14fd0fb2014-01-14 21:42:01 -080012// same implementation under linux for simplicity.
brians2fdfc072013-02-26 05:35:15 +000013
14namespace aos {
15
16// Setting function_ multiple times would be OK because it'll get set to the
17// same value each time.
18template<typename T>
19Once<T>::Once(Function function)
20 : function_(function) {
21 static_assert(shm_ok<Once<T>>::value, "Once should work in shared memory");
22}
23
24template<typename T>
25void Once<T>::Reset() {
Brian Silverman4968c202014-05-19 17:04:02 -070026 __atomic_store_n(&run_, false, __ATOMIC_SEQ_CST);
27 __atomic_store_n(&done_, false, __ATOMIC_SEQ_CST);
brians2fdfc072013-02-26 05:35:15 +000028}
29
30template<typename T>
31T *Once<T>::Get() {
Brian Silverman4968c202014-05-19 17:04:02 -070032 if (__atomic_exchange_n(&run_, true, __ATOMIC_RELAXED) == false) {
brians2fdfc072013-02-26 05:35:15 +000033 result_ = function_();
Brian Silverman4968c202014-05-19 17:04:02 -070034 __atomic_store_n(&done_, true, __ATOMIC_RELEASE);
brians2fdfc072013-02-26 05:35:15 +000035 } else {
Brian Silverman4968c202014-05-19 17:04:02 -070036 while (!__atomic_load_n(&done_, __ATOMIC_ACQUIRE)) {
brians2fdfc072013-02-26 05:35:15 +000037 sched_yield();
brians2fdfc072013-02-26 05:35:15 +000038 }
39 }
40 return result_;
41}
42
43} // namespace aos