PFUNC
1.0
|
00001 #ifndef PFUNC_CILK_HPP 00002 #define PFUNC_CILK_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 <deque> 00009 #include <pfunc/mutex.hpp> 00010 #include <pfunc/environ.hpp> 00011 #include <pfunc/exception.hpp> 00012 00013 namespace pfunc { namespace detail { 00014 00018 template <typename ValueType> 00019 struct task_queue_set <cilkS, ValueType> { 00020 typedef std::deque<ValueType*> queue_type; 00021 typedef typename queue_type::value_type value_type; 00022 typedef unsigned int queue_index_type; 00023 typedef task_queue_set_data<queue_type> data_type; 00025 ALIGN128 data_type* data; 00026 ALIGN128 unsigned int num_queues; 00027 PFUNC_DEFINE_EXCEPT_PTR() 00028 00029 00034 task_queue_set (unsigned int num_queues) PFUNC_CONSTRUCTOR_TRY_BLOCK() : 00035 num_queues (num_queues) PFUNC_EXCEPT_PTR_INIT() { 00036 PFUNC_START_TRY_BLOCK() 00037 data = new data_type [num_queues]; 00038 PFUNC_END_TRY_BLOCK() 00039 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00040 } 00041 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00042 00043 00046 ~task_queue_set ( ) { 00047 PFUNC_START_TRY_BLOCK() 00048 delete [] data; 00049 PFUNC_EXCEPT_PTR_CLEAR() 00050 PFUNC_END_TRY_BLOCK() 00051 PFUNC_CATCH_AND_RETHROW(task_queue_set,~task_queue_set) 00052 } 00053 00067 template <typename TaskPredicatePair> 00068 bool test_and_get_front (queue_index_type queue_num, 00069 const TaskPredicatePair& cnd, 00070 value_type& value) { 00071 bool ret_val = false; 00072 00073 PFUNC_START_TRY_BLOCK() 00074 queue_type& queue = data[queue_num].queue; 00075 mutex& lock = data[queue_num].lock; 00076 00077 lock.lock (); 00078 if (!queue.empty () && cnd.own_pred (queue.front())) { 00079 value = queue.front (); 00080 queue.pop_front (); 00081 ret_val = true; 00082 } 00083 lock.unlock (); 00084 00085 PFUNC_END_TRY_BLOCK() 00086 PFUNC_CATCH_AND_RETHROW(task_queue_set,test_and_get_front) 00087 00088 return ret_val; 00089 } 00090 00104 template <typename TaskPredicatePair> 00105 bool test_and_get_back (queue_index_type queue_num, 00106 const TaskPredicatePair& cnd, 00107 value_type& value) { 00108 bool ret_val = false; 00109 00110 PFUNC_START_TRY_BLOCK() 00111 queue_type& queue = data[queue_num].queue; 00112 mutex& lock = data[queue_num].lock; 00113 00114 lock.lock (); 00115 if (!queue.empty () && cnd.steal_pred (queue.back())) { 00116 value = queue.back (); 00117 queue.pop_back (); 00118 ret_val = true; 00119 } 00120 lock.unlock (); 00121 00122 PFUNC_END_TRY_BLOCK() 00123 PFUNC_CATCH_AND_RETHROW(task_queue_set,test_and_get_back) 00124 00125 return ret_val; 00126 } 00127 00142 template <typename TaskPredicatePair> 00143 value_type get (queue_index_type queue_num, 00144 const TaskPredicatePair& cnd) { 00145 value_type task = NULL; 00146 00147 PFUNC_START_TRY_BLOCK() 00148 for (int i=queue_num, num_attempts = 0; 00149 num_attempts < static_cast<int>(num_queues); 00150 ++i, ++num_attempts) { 00151 const unsigned int real_i = i % num_queues; 00152 if (real_i == queue_num) { 00153 if (test_and_get_front (real_i, cnd, task)) break; 00154 } else if (test_and_get_back (real_i, cnd, task)) break; 00155 } 00156 00157 PFUNC_END_TRY_BLOCK() 00158 PFUNC_CATCH_AND_RETHROW(task_queue_set,get) 00159 00160 return task; 00161 } 00162 00170 void put (queue_index_type queue_num, const value_type& value) { 00171 PFUNC_START_TRY_BLOCK() 00172 queue_type& queue = data[queue_num].queue; 00173 mutex& lock = data[queue_num].lock; 00174 00175 lock.lock (); 00176 queue.push_front (value); 00177 lock.unlock (); 00178 00179 PFUNC_END_TRY_BLOCK() 00180 PFUNC_CATCH_AND_RETHROW(task_queue_set,task_queue_set) 00181 } 00182 }; 00183 } /* namespace detail */ } /* namespace pfunc */ 00184 00185 #endif /* PFUNC_CILK_HPP */