PFUNC 1.0
pfunc/cilk.hpp
Go to the documentation of this file.
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 */