PFUNC 1.0
|
00001 #ifndef PFUNC_BARRIER_HPP 00002 #define PFUNC_BARRIER_HPP 00003 00010 #include <pfunc/config.h> 00011 #include <pfunc/pfunc_common.h> 00012 #include <pfunc/no_copy.hpp> 00013 #include <pfunc/exception.hpp> 00014 #include <pfunc/pfunc_atomics.h> 00015 #include <pfunc/environ.hpp> 00016 00017 #if PFUNC_HAVE_FUTEX == 1 00018 #include <pfunc/futex.h> 00019 00020 namespace pfunc { namespace detail { 00021 struct barrier : public no_copy { 00022 ALIGN64 unsigned barrier_size; 00023 ALIGN64 unsigned barrier_phase; 00024 ALIGN64 unsigned barrier_count; 00026 barrier () : barrier_size (0), barrier_phase (0), barrier_count (0) {} 00027 00031 void initialize (const unsigned int& size) { 00032 barrier_size = barrier_count = size; 00033 } 00034 00038 void operator() () { 00039 unsigned my_phase = barrier_phase; 00040 00042 if (1 == pfunc_fetch_and_add_32 (&barrier_count, -1)) { 00043 barrier_count = barrier_size; 00044 barrier_phase = ~barrier_phase; 00045 futex_wake (reinterpret_cast<int*>(&barrier_phase), INT_MAX); 00046 } else { 00047 while (barrier_phase == my_phase) { 00049 for (unsigned int i = 0; i < 2000000; i++) { 00050 if (my_phase == barrier_phase) cpu_relax (); 00051 else break; 00052 } 00054 futex_wait (reinterpret_cast<int*>(&barrier_phase), my_phase); 00055 } 00056 } 00057 } 00058 }; 00059 } /* namespace detail */ } /* namespace pfunc */ 00060 00061 #elif PFUNC_HAVE_PTHREADS == 1 || PFUNC_WINDOWS == 1 00062 #include <pfunc/mutex.hpp> 00063 #include <pfunc/cond.hpp> 00064 00065 namespace pfunc { namespace detail { 00066 struct barrier { 00067 ALIGN64 volatile bool barrier_phase; 00068 ALIGN64 volatile unsigned int barrier_count; 00069 ALIGN64 unsigned int barrier_size; 00070 mutex lck; 00071 cond cnd; 00072 PFUNC_DEFINE_EXCEPT_PTR() 00073 00074 barrier () PFUNC_CONSTRUCTOR_TRY_BLOCK() : 00075 barrier_phase (true), barrier_count (0), barrier_size (0) 00076 PFUNC_EXCEPT_PTR_INIT() {} 00077 PFUNC_CATCH_AND_RETHROW(barrier,barrier) 00078 00079 ~barrier () { PFUNC_EXCEPT_PTR_CLEAR() } 00080 00081 void initialize (const unsigned int& size) { barrier_size = size; } 00082 00084 void operator() () { 00085 PFUNC_START_TRY_BLOCK() 00086 lck.lock (); 00087 volatile bool my_phase = barrier_phase; 00088 ++barrier_count; 00089 if (barrier_count == barrier_size) { 00090 barrier_count = 0; 00091 barrier_phase = !barrier_phase; 00092 cnd.broadcast (); 00093 lck.unlock (); 00094 } else { 00095 while (my_phase == barrier_phase) cnd.wait (lck); 00096 lck.unlock (); 00097 } 00098 PFUNC_END_TRY_BLOCK() 00099 PFUNC_CATCH_AND_RETHROW(barrier,paranthesis) 00100 } 00101 }; 00102 } /* namespace detail */ } /* namespace pfunc */ 00103 #endif 00104 00105 #endif // PFUNC_HPP