1 #ifndef GENESIS_UTILS_THREADING_THREAD_FUNCTIONS_H_
2 #define GENESIS_UTILS_THREADING_THREAD_FUNCTIONS_H_
70 #include <condition_variable>
140 typename T1,
typename T2,
typename T =
typename std::common_type<T1, T2>::type,
141 typename R =
typename std::result_of<typename std::decay<F>::type(T, T)>::type
144 T1 begin, T2 end, F&& body,
145 std::shared_ptr<ThreadPool> thread_pool =
nullptr,
146 size_t num_blocks = 0,
147 bool auto_wait =
true
156 auto begin_t =
static_cast<T
>( begin );
157 auto end_t =
static_cast<T
>( end );
158 if( begin_t > end_t ) {
161 size_t const total_size = end_t - begin_t;
164 if( total_size == 0 ) {
165 assert( begin_t == end_t );
173 if( num_blocks == 0 ) {
174 num_blocks = thread_pool->size() + 1;
179 if( num_blocks > total_size ) {
180 num_blocks = total_size;
182 assert( num_blocks > 0 );
183 assert( num_blocks <= total_size );
190 size_t const block_size = total_size / num_blocks;
191 size_t const remainder = total_size % num_blocks;
192 assert( block_size > 0 );
193 assert( remainder < num_blocks );
196 size_t current_start = 0;
198 for(
size_t i = 0; i < num_blocks; ++i ) {
202 auto const l = block_size + ( i < remainder ? 1 : 0 );
203 auto const b = begin_t +
static_cast<T
>( current_start );
204 auto const e = begin_t +
static_cast<T
>( current_start + l );
207 result[i] = thread_pool->enqueue_and_retrieve( std::forward<F>( body ), b, e );
211 assert( current_start <= total_size );
216 assert( current_start == total_size );
217 assert( begin_t +
static_cast<T
>( current_start ) == end_t );
257 typename T1,
typename T2,
typename T =
typename std::common_type<T1, T2>::type
260 T1 begin, T2 end, F&& body,
261 std::shared_ptr<ThreadPool> thread_pool =
nullptr,
262 size_t num_blocks = 0,
263 bool auto_wait =
true
268 for( T i = b; i < e; ++i ) {
305 template<
typename F,
typename T>
307 T
const begin, T
const end, F&& body,
308 std::shared_ptr<ThreadPool> thread_pool =
nullptr,
309 size_t num_blocks = 0,
310 bool auto_wait =
true
313 auto const total = std::distance( begin, end );
315 throw std::invalid_argument(
"Cannot use parallel_for_each() with a reverse range." );
331 [begin, body](
size_t b,
size_t e ){
332 for(
size_t i = b; i < e; ++i ) {
333 body( *(begin + i) );
368 template<
typename F,
typename T>
370 T& container, F&& body,
371 std::shared_ptr<ThreadPool> thread_pool =
nullptr,
372 size_t num_blocks = 0,
373 bool auto_wait =
true
376 if( container.size() == 0 ) {
383 [&container, body](
size_t b,
size_t e ) {
384 for( size_t i = b; i < e; ++i ) {
385 body( container[ i ] );
438 template<
typename Tag>
445 get_static_mutex_().lock();
450 get_static_mutex_().unlock();
455 static std::mutex& get_static_mutex_()
457 static std::mutex mutex_;
463 #define GENESIS_THREAD_CRITICAL_SECTION(TagName) \
465 ThreadCriticalSection<TagName> genesis_critical_section_##TagName;
470 #endif // include guard