40 #ifndef _GLIBCXX_PARALLEL_WORKSTEALING_H
41 #define _GLIBCXX_PARALLEL_WORKSTEALING_H 1
47 namespace __gnu_parallel
50 #define _GLIBCXX_JOB_VOLATILE volatile
53 template<
typename _DifferenceTp>
56 typedef _DifferenceTp _DifferenceType;
62 _GLIBCXX_JOB_VOLATILE _DifferenceType
_M_first;
67 _GLIBCXX_JOB_VOLATILE _DifferenceType
_M_last;
72 _GLIBCXX_JOB_VOLATILE _DifferenceType
_M_load;
93 template<
typename _RAIter,
100 _RAIter __end, _Op __op,
104 typename std::iterator_traits<_RAIter>::difference_type __bound)
108 typedef std::iterator_traits<_RAIter> _TraitsType;
109 typedef typename _TraitsType::difference_type _DifferenceType;
113 _DifferenceType __chunk_size =
114 static_cast<_DifferenceType
>(__s.workstealing_chunk_size);
117 _DifferenceType __length = (__bound < 0) ? (__end - __begin) : __bound;
128 omp_lock_t __output_lock;
129 omp_init_lock(&__output_lock);
135 _ThreadIndex __num_threads = __gnu_parallel::max<_ThreadIndex>
136 (1, __gnu_parallel::min<_DifferenceType>(__length,
137 __get_max_threads()));
139 # pragma omp parallel shared(__busy) num_threads(__num_threads)
143 __num_threads = omp_get_num_threads();
152 bool __iam_working =
false;
164 _Result __result = _Result();
167 _DifferenceType __steal;
177 __iam_working =
true;
180 __my_job.
_M_first =
static_cast<_DifferenceType
>
181 (__iam * (__length / __num_threads));
183 __my_job.
_M_last = (__iam == (__num_threads - 1)
185 : ((__iam + 1) * (__length / __num_threads) - 1));
192 _DifferenceType __my_first = __my_job.
_M_first;
193 __result = __f(__op, __begin + __my_first);
207 # pragma omp flush(__busy)
214 _DifferenceType __current_job =
215 __fetch_and_add<_DifferenceType>(&(__my_job.
_M_first),
221 for (_DifferenceType __job_counter = 0;
222 __job_counter < __chunk_size
223 && __current_job <= __my_job.
_M_last;
227 __current = __begin + __current_job;
231 __result = __r(__result, __f(__op, __current));
234 # pragma omp flush(__busy)
244 __iam_working =
false;
247 _DifferenceType __supposed_first, __supposed_last,
253 # pragma omp flush(__busy)
254 __victim = __rand_gen();
255 __supposed_first = __job[__victim * __stride].
_M_first;
256 __supposed_last = __job[__victim * __stride].
_M_last;
257 __supposed_load = __job[__victim * __stride].
_M_load;
260 && ((__supposed_load <= 0)
261 || ((__supposed_first + __supposed_load - 1)
262 != __supposed_last)));
267 if (__supposed_load > 0)
271 __steal = (__supposed_load < 2) ? 1 : __supposed_load / 2;
274 _DifferenceType __stolen_first =
275 __fetch_and_add<_DifferenceType>
276 (&(__job[__victim * __stride].
_M_first), __steal);
277 _DifferenceType __stolen_try = (__stolen_first + __steal
278 - _DifferenceType(1));
288 __iam_working =
true;
290 # pragma omp flush(__busy)
292 # pragma omp flush(__busy)
295 omp_set_lock(&__output_lock);
296 __output = __r(__output, __result);
297 omp_unset_lock(&__output_lock);
304 __f._M_finish_iterator = __begin + __length;
306 omp_destroy_lock(&__output_lock);