00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __TBB__aggregator_H
00030 #define __TBB__aggregator_H
00031
00032 #if !TBB_PREVIEW_AGGREGATOR
00033 #error Set TBB_PREVIEW_AGGREGATOR before including aggregator.h
00034 #endif
00035
00036 #include "atomic.h"
00037 #include "tbb_profiling.h"
00038
00039 namespace tbb {
00040 namespace interface6 {
00041
00042 using namespace tbb::internal;
00043
00044 class aggregator_operation {
00045 template<typename handler_type> friend class aggregator_ext;
00046 uintptr_t status;
00047 aggregator_operation* my_next;
00048 public:
00049 enum aggregator_operation_status { agg_waiting=0, agg_finished };
00050 aggregator_operation() : status(agg_waiting), my_next(NULL) {}
00052 void start() { call_itt_notify(acquired, &status); }
00054
00055 void finish() { itt_store_word_with_release(status, uintptr_t(agg_finished)); }
00056 aggregator_operation* next() { return itt_hide_load_word(my_next);}
00057 void set_next(aggregator_operation* n) { itt_hide_store_word(my_next, n); }
00058 };
00059
00060 namespace internal {
00061
00062 class basic_operation_base : public aggregator_operation {
00063 friend class basic_handler;
00064 virtual void apply_body() = 0;
00065 public:
00066 basic_operation_base() : aggregator_operation() {}
00067 virtual ~basic_operation_base() {}
00068 };
00069
00070 template<typename Body>
00071 class basic_operation : public basic_operation_base, no_assign {
00072 const Body& my_body;
00073 void apply_body() { my_body(); }
00074 public:
00075 basic_operation(const Body& b) : basic_operation_base(), my_body(b) {}
00076 };
00077
00078 class basic_handler {
00079 public:
00080 basic_handler() {}
00081 void operator()(aggregator_operation* op_list) const {
00082 while (op_list) {
00083
00084
00085
00086
00087
00088
00089 basic_operation_base& request = static_cast<basic_operation_base&>(*op_list);
00090
00091 op_list = op_list->next();
00092 request.start();
00093 request.apply_body();
00094 request.finish();
00095 }
00096 }
00097 };
00098
00099 }
00100
00102
00104 template <typename handler_type>
00105 class aggregator_ext : tbb::internal::no_copy {
00106 public:
00107 aggregator_ext(const handler_type& h) : handler_busy(0), handle_operations(h) { mailbox = NULL; }
00108
00110
00111 void process(aggregator_operation *op) { execute_impl(*op); }
00112
00113 protected:
00116 void execute_impl(aggregator_operation& op) {
00117 aggregator_operation* res;
00118
00119
00120
00121
00122
00123
00124 call_itt_notify(releasing, &(op.status));
00125
00126 do {
00127
00128
00129 op.my_next = res = mailbox;
00130 } while (mailbox.compare_and_swap(&op, res) != res);
00131 if (!res) {
00132
00133
00134 call_itt_notify(acquired, &mailbox);
00135 start_handle_operations();
00136 __TBB_ASSERT(op.status, NULL);
00137 }
00138 else {
00139 call_itt_notify(prepare, &(op.status));
00140 spin_wait_while_eq(op.status, uintptr_t(aggregator_operation::agg_waiting));
00141 itt_load_word_with_acquire(op.status);
00142 }
00143 }
00144
00145
00146 private:
00148 atomic<aggregator_operation *> mailbox;
00149
00151
00152 uintptr_t handler_busy;
00153
00154 handler_type handle_operations;
00155
00157 void start_handle_operations() {
00158 aggregator_operation *pending_operations;
00159
00160
00161
00162
00163
00164
00165
00166 call_itt_notify(prepare, &handler_busy);
00167
00168 spin_wait_until_eq(handler_busy, uintptr_t(0));
00169 call_itt_notify(acquired, &handler_busy);
00170
00171 __TBB_store_with_release(handler_busy, uintptr_t(1));
00172
00173
00174
00175
00176 call_itt_notify(releasing, &mailbox);
00177
00178 pending_operations = mailbox.fetch_and_store(NULL);
00179
00180
00181 handle_operations(pending_operations);
00182
00183
00184 itt_store_word_with_release(handler_busy, uintptr_t(0));
00185 }
00186 };
00187
00189 class aggregator : private aggregator_ext<internal::basic_handler> {
00190 public:
00191 aggregator() : aggregator_ext<internal::basic_handler>(internal::basic_handler()) {}
00193
00195 template<typename Body>
00196 void execute(const Body& b) {
00197 internal::basic_operation<Body> op(b);
00198 this->execute_impl(op);
00199 }
00200 };
00201
00202 }
00203
00204 using interface6::aggregator;
00205 using interface6::aggregator_ext;
00206 using interface6::aggregator_operation;
00207
00208 }
00209
00210 #endif // __TBB__aggregator_H