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