Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
once.cpp
Go to the documentation of this file.
1
29#define _RWSTD_LIB_SRC
30#include <rw/_defs.h>
31#include <rw/_mutex.h>
32
33#include "once.h"
34
35
37
38
39extern "C" {
40
41
42#ifdef _RWSTD_THREAD_ONCE
43
44
45// implementation that relies on the system one-time initialization
46// mechanism such as pthread_once()
48__rw_once (__rw_once_t *once, void (*func)())
49{
50 _RWSTD_ASSERT (0 != once && 0 != func);
51
52 return _RWSTD_THREAD_ONCE (once, func);
53}
54
55
56#elif defined (_RWSTD_NO_ATOMIC_OPS) && defined (_RWSTD_POSIX_THREADS)
57
58
59// implementation that uses a mutex instead of pthread_once() or atomic
60// operations
62__rw_once (__rw_once_t *once, void (*func)())
63{
64 _RWSTD_ASSERT (0 != once && 0 != func);
65
66 // _C_init may take on one of two valid values:
67 // -1 for a properly initialized __rw_once_t object whose initializer
68 // hasn't run yet
69 // +1 for ar __rw_once_t object whose initializer has already been
70 // executed
71 // Any other value (including 0, for __rw_once_t objects that haven't
72 // been properly initialized) is invalid.
73
74 if (-1 == once->_C_init) {
75
76 const int result = pthread_mutex_lock (&once->_C_mutex);
77 if (result)
78 return result;
79
80 if (-1 == once->_C_init) {
81
82 // entered by the first thread and only the first time around,
83 // unless the initialization function throws
84
85 _TRY {
86 func ();
87 }
88 _CATCH (...) {
89 pthread_mutex_unlock (&once->_C_mutex);
91 }
92
93 once->_C_init += 2;
94 }
95
96 pthread_mutex_unlock (&once->_C_mutex);
97 }
98
99 // verify that initialization took place exactly once and help detect
100 // uninitialized __rw_once_t objects to help catch problems on platforms
101 // such as HP-UX that require pthread_once_t objects to be explicitly
102 // initialized (i.e., not all bits tobe zeroed out) in order for
103 // pthread_once() to succeed
104 _RWSTD_ASSERT (1 == once->_C_init);
105
106 return 0;
107}
108
109
110#elif defined (_RWSTD_REENTRANT)
111
112
113// implementation that uses atomic operations
114#ifndef _RWSTD_MSVC
116__rw_once (__rw_once_t *once, void (*func)())
117#else
119__rw_once (__rw_once_t *once, void (*func)() throw (...)) throw (...)
120#endif
121{
122 _RWSTD_ASSERT (0 != once && 0 != func);
123
124 volatile int &init = once->_C_init;
125
126restart:
127
128 // cast init to int& (see STDCXX-792)
129 // casting should be removed after fixing STDCXX-794
130 if (init == 0 && 1 == _RWSTD_ATOMIC_PREINCREMENT (
131 _RWSTD_CONST_CAST (int&, init), false)) {
132
133 // entered by the first thread and only the first time around,
134 // unless the initialization function throws
135
136 _TRY {
137 func ();
138 }
139 _CATCH (...) {
141 _RWSTD_CONST_CAST (int&, init), false);
142 _RETHROW;
143 }
144
145 init = 1000;
146 }
147 else {
148 // entered by the second and subsequent threads or on the second
149 // and subsequent calls by the first thread after (or duing)
150 // a successful initialization
151
152 for (int loop = 0; init < 1000; ++loop) {
153 if (0 == init) {
154 // first time initialization failed via an exception,
155 // try again
156 goto restart;
157 }
158
159 if (32 < loop) {
160 // avoid wasting too many CPU cycles
162 }
163 }
164 }
165
166 return 0;
167}
168
169
170#else // if !defined (_RWSTD_THREAD_ONCE)
171
172
173// thread-unsafe implementation
175__rw_once (__rw_once_t *once, void (*func)())
176{
177 _RWSTD_ASSERT (0 != once && 0 != func);
178
179 // detect uninitialized __rw_once_t objects to help reveal problems
180 // in reentrant code on platforms such as HP-UX that require
181 // pthread_once_t objects to be explicitly initialized (i.e., not
182 // all bits tobe zeroed out) in order for pthread_once() to succeed
183 _RWSTD_ASSERT (-1 == once->_C_init || 1 == once->_C_init);
184
185 if (once->_C_init == -1) {
186
187 func ();
188
189 once->_C_init = 1;
190 }
191
192 return 0;
193}
194
195#endif // _RWSTD_THREAD_ONCE
196
197} // extern "C"
198
199} // namespace __rw
volatile int result
#define _RWSTD_EXPORT
Definition _defs.h:485
#define _RWSTD_ATOMIC_PREINCREMENT(x, ignore)
Definition _defs.h:699
#define _RETHROW
Definition _defs.h:853
#define _TRY
Definition _defs.h:850
#define _RWSTD_NAMESPACE(name)
Definition _defs.h:567
#define _RWSTD_ATOMIC_PREDECREMENT(x, ignore)
Definition _defs.h:700
#define _RWSTD_ASSERT(ignore)
Definition _defs.h:1108
#define _CATCH(ex)
Definition _defs.h:851
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
std::mbstate_t init
Definition codecvt1.cpp:80
#define _RWSTD_THREAD_YIELD()
Definition once.h:128