18 #ifndef LIBMESH_THREADS_PTHREAD_H
19 #define LIBMESH_THREADS_PTHREAD_H
23 #ifndef LIBMESH_SQUASH_HEADER_WARNING
24 # warning "This file is designed to be included through libmesh/threads.h"
27 #ifdef LIBMESH_HAVE_PTHREAD
30 #ifdef LIBMESH_HAVE_CXX11_THREAD
34 #include "libmesh/libmesh_logging.h"
43 # include <libkern/OSAtomic.h>
48 #ifdef LIBMESH_HAVE_CXX11_THREAD
49 # define LIBMESH_TLS_TYPE(type) thread_local type
50 # define LIBMESH_TLS_REF(value) (value)
51 #else // Maybe support gcc __thread eventually?
52 # define LIBMESH_TLS_TYPE(type) type
53 # define LIBMESH_TLS_REF(value) (value)
63 #ifdef LIBMESH_HAVE_CXX11_THREAD
67 typedef std::thread
Thread;
74 typedef NonConcurrentThread
Thread;
76 #endif // LIBMESH_HAVE_CXX11_THREAD
184 pthread_mutexattr_init(&
attr);
185 pthread_mutexattr_settype(&
attr, PTHREAD_MUTEX_RECURSIVE);
213 template <
typename Range>
217 return min > 0 ? cast_int<unsigned int>(min) : 1;
220 template <
typename Range,
typename Body>
228 template <
typename Range,
typename Body>
233 Body & body = *range_body->
body;
234 Range & range = *range_body->
range;
268 template <
typename Range,
typename Body>
270 void parallel_for (
const Range & range,
const Body & body)
281 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
290 std::vector<RangeBody<const Range, const Body>> range_bodies(
n_threads);
291 std::vector<pthread_t> threads(
n_threads);
294 std::size_t range_size = range.size() /
n_threads;
296 typename Range::const_iterator current_beginning = range.begin();
300 std::size_t this_range_size = range_size;
303 this_range_size += range.size() %
n_threads;
305 ranges[i] =
new Range(range, current_beginning, current_beginning + this_range_size);
307 current_beginning = current_beginning + this_range_size;
313 range_bodies[i].range = ranges[i];
314 range_bodies[i].body = &body;
321 #ifdef LIBMESH_HAVE_OPENMP
322 #pragma omp parallel for schedule (static)
326 #if !LIBMESH_HAVE_OPENMP
327 pthread_create(&threads[i],
nullptr, &run_body<Range, Body>, (
void *)&range_bodies[i]);
329 run_body<Range, Body>((
void *)&range_bodies[i]);
333 #if !LIBMESH_HAVE_OPENMP
342 for (
int i=0; i<static_cast<int>(
n_threads); i++)
343 pthread_join(threads[i],
nullptr);
350 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
360 template <
typename Range,
typename Body,
typename Partitioner>
362 void parallel_for (
const Range & range,
const Body & body,
const Partitioner &)
371 template <
typename Range,
typename Body>
384 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
395 std::vector<RangeBody<Range, Body>> range_bodies(
n_threads);
403 std::size_t range_size = range.size() /
n_threads;
405 typename Range::const_iterator current_beginning = range.begin();
409 std::size_t this_range_size = range_size;
412 this_range_size += range.size() %
n_threads;
414 ranges[i] =
new Range(range, current_beginning, current_beginning + this_range_size);
416 current_beginning = current_beginning + this_range_size;
422 range_bodies[i].range = ranges[i];
423 range_bodies[i].body = bodies[i];
427 std::vector<pthread_t> threads(
n_threads);
432 #ifdef LIBMESH_HAVE_OPENMP
433 #pragma omp parallel for schedule (static)
441 for (
int i=0; i<static_cast<int>(
n_threads); i++)
443 #if !LIBMESH_HAVE_OPENMP
444 pthread_create(&threads[i],
nullptr, &run_body<Range, Body>, (
void *)&range_bodies[i]);
446 run_body<Range, Body>((
void *)&range_bodies[i]);
450 #if !LIBMESH_HAVE_OPENMP
453 pthread_join(threads[i],
nullptr);
457 for (
unsigned int i=
n_threads-1; i != 0; i--)
458 bodies[i-1]->join(*bodies[i]);
466 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
476 template <
typename Range,
typename Body,
typename Partitioner>
478 void parallel_reduce (
const Range & range, Body & body,
const Partitioner &)
488 template <
typename T>
493 operator T () {
return val; }
497 spin_mutex::scoped_lock lock(
smutex);
504 spin_mutex::scoped_lock lock(
smutex);
512 spin_mutex::scoped_lock lock(
smutex);
519 spin_mutex::scoped_lock lock(
smutex);
526 spin_mutex::scoped_lock lock(
smutex);
533 spin_mutex::scoped_lock lock(
smutex);
540 spin_mutex::scoped_lock lock(
smutex);
547 spin_mutex::scoped_lock lock(
smutex);
561 #endif // #ifdef LIBMESH_HAVE_PTHREAD
563 #endif // LIBMESH_SQUASH_HEADER_WARNING
565 #endif // LIBMESH_THREADS_PTHREAD_H