Intel(R) Threading Building Blocks Doxygen Documentation version 4.2.3
Loading...
Searching...
No Matches
_aggregator_impl.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2005-2020 Intel Corporation
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17#ifndef __TBB__aggregator_impl_H
18#define __TBB__aggregator_impl_H
19
20#include "../atomic.h"
21#if !__TBBMALLOC_BUILD
22#include "../tbb_profiling.h"
23#endif
24
25namespace tbb {
26namespace interface6 {
27namespace internal {
28
29using namespace tbb::internal;
30
32template <typename Derived>
34 public:
36 uintptr_t status;
37
38 Derived *next;
40};
41
43
48template < typename operation_type >
50public:
52
54
63 template < typename handler_type >
64 void execute(operation_type *op, handler_type &handle_operations, bool long_life_time = true) {
65 operation_type *res;
66 // op->status should be read before inserting the operation into the
67 // aggregator waitlist since it can become invalid after executing a
68 // handler (if the operation has 'short' life time.)
69 const uintptr_t status = op->status;
70
71 // ITT note: &(op->status) tag is used to cover accesses to this op node. This
72 // thread has created the operation, and now releases it so that the handler
73 // thread may handle the associated operation w/o triggering a race condition;
74 // thus this tag will be acquired just before the operation is handled in the
75 // handle_operations functor.
76 call_itt_notify(releasing, &(op->status));
77 // insert the operation in the queue.
78 do {
79 // Tools may flag the following line as a race; it is a false positive:
80 // This is an atomic read; we don't provide itt_hide_load_word for atomics
81 op->next = res = pending_operations; // NOT A RACE
82 } while (pending_operations.compare_and_swap(op, res) != res);
83 if (!res) { // first in the list; handle the operations.
84 // ITT note: &pending_operations tag covers access to the handler_busy flag,
85 // which this waiting handler thread will try to set before entering
86 // handle_operations.
88 start_handle_operations(handle_operations);
89 // The operation with 'short' life time can already be destroyed.
90 if (long_life_time)
91 __TBB_ASSERT(op->status, NULL);
92 }
93 // not first; wait for op to be ready.
94 else if (!status) { // operation is blocking here.
95 __TBB_ASSERT(long_life_time, "Waiting for an operation object that might be destroyed during processing.");
96 call_itt_notify(prepare, &(op->status));
97 spin_wait_while_eq(op->status, uintptr_t(0));
99 }
100 }
101
102 private:
104 atomic<operation_type *> pending_operations;
106 uintptr_t handler_busy;
107
109 template < typename handler_type >
110 void start_handle_operations( handler_type &handle_operations ) {
111 operation_type *op_list;
112
113 // ITT note: &handler_busy tag covers access to pending_operations as it is passed
114 // between active and waiting handlers. Below, the waiting handler waits until
115 // the active handler releases, and the waiting handler acquires &handler_busy as
116 // it becomes the active_handler. The release point is at the end of this
117 // function, when all operations in pending_operations have been handled by the
118 // owner of this aggregator.
120 // get the handler_busy:
121 // only one thread can possibly spin here at a time
122 spin_wait_until_eq(handler_busy, uintptr_t(0));
124 // acquire fence not necessary here due to causality rule and surrounding atomics
126
127 // ITT note: &pending_operations tag covers access to the handler_busy flag
128 // itself. Capturing the state of the pending_operations signifies that
129 // handler_busy has been set and a new active handler will now process that list's
130 // operations.
132 // grab pending_operations
133 op_list = pending_operations.fetch_and_store(NULL);
134
135 // handle all the operations
136 handle_operations(op_list);
137
138 // release the handler
140 }
141};
142
143template < typename handler_type, typename operation_type >
144class aggregator : public aggregator_generic<operation_type> {
145 handler_type handle_operations;
146public:
148 explicit aggregator(handler_type h) : handle_operations(h) {}
149
150 void initialize_handler(handler_type h) { handle_operations = h; }
151
152 void execute(operation_type *op) {
154 }
155};
156
157// the most-compatible friend declaration (vs, gcc, icc) is
158// template<class U, class V> friend class aggregating_functor;
159template<typename aggregating_class, typename operation_list>
161 aggregating_class *fi;
162public:
164 aggregating_functor(aggregating_class *fi_) : fi(fi_) {}
165 void operator()(operation_list* op_list) { fi->handle_operations(op_list); }
166};
167
168} // namespace internal
169} // namespace interface6
170
171namespace internal {
176} // namespace internal
177
178} // namespace tbb
179
180#endif // __TBB__aggregator_impl_H
#define __TBB_ASSERT(predicate, comment)
No-op version of __TBB_ASSERT.
Definition: tbb_stddef.h:165
void const char const char int ITT_FORMAT __itt_group_sync x void const char ITT_FORMAT __itt_group_sync s void ITT_FORMAT __itt_group_sync p void ITT_FORMAT p void ITT_FORMAT p no args __itt_suppress_mode_t unsigned int void size_t ITT_FORMAT d void ITT_FORMAT p void ITT_FORMAT p __itt_model_site __itt_model_site_instance ITT_FORMAT p __itt_model_task __itt_model_task_instance ITT_FORMAT p void ITT_FORMAT p void ITT_FORMAT p void size_t ITT_FORMAT d void ITT_FORMAT p const wchar_t ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s const char ITT_FORMAT s no args void ITT_FORMAT p size_t ITT_FORMAT d no args const wchar_t const wchar_t ITT_FORMAT s __itt_heap_function h
The graph class.
Identifiers declared inside namespace internal should never be used directly by client code.
Definition: atomic.h:65
void spin_wait_until_eq(const volatile T &location, const U value)
Spin UNTIL the value of the variable is equal to a given value.
Definition: tbb_machine.h:399
T itt_load_word_with_acquire(const tbb::atomic< T > &src)
void itt_store_word_with_release(tbb::atomic< T > &dst, U src)
void call_itt_notify(notify_type, void *)
void __TBB_store_with_release(volatile T &location, V value)
Definition: tbb_machine.h:713
void spin_wait_while_eq(const volatile T &location, U value)
Spin WHILE the value of the variable is equal to a given value.
Definition: tbb_machine.h:391
uintptr_t status
Zero value means "wait" status, all other values are "user" specified values and are defined into the...
atomic< operation_type * > pending_operations
An atomically updated list (aka mailbox) of pending operations.
void execute(operation_type *op, handler_type &handle_operations, bool long_life_time=true)
Execute an operation.
uintptr_t handler_busy
Controls thread access to handle_operations.
void start_handle_operations(handler_type &handle_operations)
Trigger the handling of operations when the handler is free.

Copyright © 2005-2020 Intel Corporation. All Rights Reserved.

Intel, Pentium, Intel Xeon, Itanium, Intel XScale and VTune are registered trademarks or trademarks of Intel Corporation or its subsidiaries in the United States and other countries.

* Other names and brands may be claimed as the property of others.