Author: sebor
Date: Fri Aug 17 15:02:52 2007
New Revision: 567159
URL: http://svn.apache.org/viewvc?view=rev&rev=567159
Log:
2007-08-17 Martin Sebor <[EMAIL PROTECTED]>
* once.h (_RWSTD_ONCE_INIT): Defined to PTHREAD_ONCE_INIT.
[_RWSTD_POSIX_THREADS, _RWSTD_NO_PTHREAD_ONCE] (__rw_once_t,
_RWSTD_ONCE_INIT): Defined in terms of pthread_mutex_t and
PTHREAD_MUTEX_INITIALIZER, respectively.
* once.cpp [_RWSTD_POSIX_THREADS, _RWSTD_NO_PTHREAD_ONCE]
(__rw_once_t): Defined in terms of pthread_mutex_lock()
and pthread_mutex_unlock().
(__rw_once_t): Consistently asserted both preconditions.
Modified:
incubator/stdcxx/trunk/src/once.cpp
incubator/stdcxx/trunk/src/once.h
Modified: incubator/stdcxx/trunk/src/once.cpp
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/src/once.cpp?view=diff&rev=567159&r1=567158&r2=567159
==============================================================================
--- incubator/stdcxx/trunk/src/once.cpp (original)
+++ incubator/stdcxx/trunk/src/once.cpp Fri Aug 17 15:02:52 2007
@@ -42,20 +42,79 @@
#ifdef _RWSTD_THREAD_ONCE
+// implementation that relies on the system one-time initialization
+// mechanism such as pthread_once()
_RWSTD_EXPORT int
__rw_once (__rw_once_t *once, void (*func)())
{
+ _RWSTD_ASSERT (0 != once && 0 != func);
+
return _RWSTD_THREAD_ONCE (once, func);
}
+#elif defined (_RWSTD_NO_ATOMIC_OPS) && defined (_RWSTD_POSIX_THREADS)
+
+
+// implementation that uses a mutex instead of pthread_once() or atomic
+// operations
+_RWSTD_EXPORT int
+__rw_once (__rw_once_t *once, void (*func)())
+{
+ _RWSTD_ASSERT (0 != once && 0 != func);
+
+ // _C_init may take on one of two valid values:
+ // -1 for a properly initialized __rw_once_t object whose initializer
+ // hasn't run yet
+ // +1 for ar __rw_once_t object whose initializer has already been
+ // executed
+ // Any other value (including 0, for __rw_once_t objects that haven't
+ // been properly initialized) is invalid.
+
+ if (-1 == once->_C_init) {
+
+ const int result = pthread_mutex_lock (&once->_C_mutex);
+ if (result)
+ return result;
+
+ if (-1 == once->_C_init) {
+
+ // entered by the first thread and only the first time around,
+ // unless the initialization function throws
+
+ _TRY {
+ func ();
+ }
+ _CATCH (...) {
+ pthread_mutex_unlock (&once->_C_mutex);
+ _RETHROW;
+ }
+
+ once->_C_init += 2;
+ }
+
+ pthread_mutex_unlock (&once->_C_mutex);
+ }
+
+ // verify that initialization took place exactly once and help detect
+ // uninitialized __rw_once_t objects to help catch problems on platforms
+ // such as HP-UX that require pthread_once_t objects to be explicitly
+ // initialized (i.e., not all bits tobe zeroed out) in order for
+ // pthread_once() to succeed
+ _RWSTD_ASSERT (1 == once->_C_init);
+
+ return 0;
+}
+
+
#elif defined (_RWSTD_REENTRANT)
+// implementation that uses atomic operations
_RWSTD_EXPORT int
__rw_once (__rw_once_t *once, void (*func)())
{
- _RWSTD_ASSERT (0 != once);
+ _RWSTD_ASSERT (0 != once && 0 != func);
volatile int &init = once->_C_init;
@@ -102,10 +161,11 @@
#else // if !defined (_RWSTD_THREAD_ONCE)
+// thread-unsafe implementation
_RWSTD_EXPORT int
__rw_once (__rw_once_t *once, void (*func)())
{
- _RWSTD_ASSERT (0 != once);
+ _RWSTD_ASSERT (0 != once && 0 != func);
// detect uninitialized __rw_once_t objects to help reveal problems
// in reentrant code on platforms such as HP-UX that require
Modified: incubator/stdcxx/trunk/src/once.h
URL:
http://svn.apache.org/viewvc/incubator/stdcxx/trunk/src/once.h?view=diff&rev=567159&r1=567158&r2=567159
==============================================================================
--- incubator/stdcxx/trunk/src/once.h (original)
+++ incubator/stdcxx/trunk/src/once.h Fri Aug 17 15:02:52 2007
@@ -37,6 +37,7 @@
# define _RWSTD_THREAD_ONCE(once, func) pthread_once (once, func)
# define _RWSTD_THREAD_YIELD() thr_yield ()
+# define _RWSTD_ONCE_INIT PTHREAD_ONCE_INIT
typedef pthread_once_t __rw_once_t;
@@ -44,9 +45,27 @@
# include <pthread.h>
+# ifndef _RWSTD_NO_PTHREAD_ONCE
+
typedef pthread_once_t __rw_once_t;
-# define _RWSTD_THREAD_ONCE(once, func) pthread_once (once, func)
+# define _RWSTD_THREAD_ONCE(once, func) pthread_once (once, func)
+# define _RWSTD_ONCE_INIT PTHREAD_ONCE_INIT
+
+# else // if defined (_RWSTD_NO_PTHREAD_ONCE)
+
+_RWSTD_NAMESPACE (__rw) {
+
+struct __rw_once_t {
+ pthread_mutex_t _C_mutex;
+ int _C_init;
+};
+
+} // namespace __rw
+
+# define _RWSTD_ONCE_INIT { PTHREAD_MUTEX_INITIALIZER, -1 }
+
+# endif // _RWSTD_NO_PTHREAD_ONCE
# ifndef _RWSTD_NO_SCHED_YIELD
# define _RWSTD_THREAD_YIELD() sched_yield ()
@@ -59,35 +78,48 @@
# include <dce/pthread.h>
# endif
+_RWSTD_NAMESPACE (__rw) {
+
typedef pthread_once_t __rw_once_t;
+} // namespace __rw
+
# define _RWSTD_THREAD_ONCE(once, func) pthread_once (once, func)
# define _RWSTD_THREAD_YIELD() pthread_yield ()
+# define _RWSTD_ONCE_INIT PTHREAD_ONCE_INIT
# elif defined (_WIN32)
# include <windows.h>
+_RWSTD_NAMESPACE (__rw) {
+
struct __rw_once_t { int _C_init; };
+} // namespace __rw
+
# define _RWSTD_THREAD_YIELD() Sleep (0)
-# endif // _RWSTD_*_THREADS
+# else // !_WIN32
+
+_RWSTD_NAMESPACE (__rw) {
+struct __rw_once_t { int _C_init; };
-# ifdef PTHREAD_ONCE_INIT
-# define _RWSTD_ONCE_INIT PTHREAD_ONCE_INIT
-# endif // PTHREAD_ONCE_INIT
+} // namespace __rw
+# define _RWSTD_ONCE_INIT { 0 }
+# endif // _WIN32
#else // if !defined (_RWSTD_REENTRANT)
+_RWSTD_NAMESPACE (__rw) {
+
struct __rw_once_t { int _C_init; };
+} // namespace __rw
+
// defined to a non-zero value to help detect uninitialized
// __rw_once_t objects
# define _RWSTD_ONCE_INIT { -1 }
-
- // not defined
-# undef _RWSTD_THREAD_ONCE
#endif // _RWSTD_REENTRANT