PFUNC 1.0
|
00001 #ifndef PFUNC_LIFO_HPP 00002 #define PFUNC_LIFO_HPP 00003 00004 #ifndef PFUNC_SCHEDULER_HPP 00005 #error "This file can only be included from task_queue_set.hpp" 00006 #endif 00007 00008 #include <stack> 00009 #include <pfunc/mutex.hpp> 00010 #include <pfunc/exception.hpp> 00011 00012 namespace pfunc { namespace detail { 00013 00017 template <typename ValueType> 00018 struct task_queue_set <lifoS, ValueType> { 00019 typedef std::stack<ValueType*> queue_type; 00020 typedef typename queue_type::value_type value_type; 00021 typedef unsigned int queue_index_type; 00022 typedef task_queue_set_data<queue_type> data_type; 00024 ALIGN128 data_type* data; 00025 ALIGN128 unsigned int num_queues; 00026 PFUNC_DEFINE_EXCEPT_PTR() 00027 00028 00033 task_queue_set (unsigned int num_queues) PFUNC_CONSTRUCTOR_TRY_BLOCK() : 00034 num_queues (num_queues) PFUNC_EXCEPT_PTR_INIT() { 00035 PFUNC_START_TRY_BLOCK() 00036 data = new data_type [num_queues]; 00037 PFUNC_END_TRY_BLOCK() 00038 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00039 } 00040 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00041 00042 00045 ~task_queue_set ( ) { 00046 PFUNC_START_TRY_BLOCK() 00047 delete [] data; 00048 PFUNC_EXCEPT_PTR_CLEAR() 00049 PFUNC_END_TRY_BLOCK() 00050 PFUNC_CATCH_AND_RETHROW(task_queue_set,~task_queue_set) 00051 } 00052 00067 template <typename TaskPredicatePair> 00068 bool test_and_get (queue_index_type queue_num, 00069 const TaskPredicatePair& cnd, 00070 value_type& value, 00071 bool own_queue) { 00072 bool ret_val = false; 00073 00074 PFUNC_START_TRY_BLOCK() 00075 queue_type& queue = data[queue_num].queue; 00076 mutex& lock = data[queue_num].lock; 00077 00078 lock.lock (); 00079 if (!queue.empty () && 00080 ((own_queue)?cnd.own_pred(queue.top()):cnd.steal_pred(queue.top()))) { 00081 value = queue.top (); 00082 queue.pop (); 00083 ret_val = true; 00084 } 00085 lock.unlock (); 00086 00087 PFUNC_END_TRY_BLOCK() 00088 PFUNC_CATCH_AND_RETHROW(task_queue_set,test_and_get) 00089 00090 return ret_val; 00091 } 00092 00105 template <typename TaskPredicatePair> 00106 value_type get (queue_index_type queue_num, 00107 const TaskPredicatePair& cnd) { 00108 value_type task = NULL; 00109 00110 PFUNC_START_TRY_BLOCK() 00111 for (int i=queue_num, num_attempts = 0; 00112 num_attempts < static_cast<int>(num_queues); 00113 ++i, ++num_attempts) { 00114 const unsigned int real_i = i % num_queues; 00115 if (test_and_get (real_i, cnd, task, (real_i==queue_num))) break; 00116 } 00117 00118 PFUNC_END_TRY_BLOCK() 00119 PFUNC_CATCH_AND_RETHROW(task_queue_set,get) 00120 00121 return task; 00122 } 00123 00131 void put (queue_index_type queue_num, const value_type& value) { 00132 PFUNC_START_TRY_BLOCK() 00133 queue_type& queue = data[queue_num].queue; 00134 mutex& lock = data[queue_num].lock; 00135 00136 lock.lock (); 00137 queue.push (value); 00138 lock.unlock (); 00139 00140 PFUNC_END_TRY_BLOCK() 00141 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00142 } 00143 }; 00144 } /* namespace detail */ } /* namespace pfunc */ 00145 00146 #endif /* PFUNC_LIFO_HPP */