PLaSK library
Loading...
Searching...
No Matches
parallel.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__PLASK_PARALLEL_H
15#define PLASK__PLASK_PARALLEL_H
16
17#include <plask/config.hpp>
18
19#ifdef OPENMP_FOUND
20# include <omp.h>
21#endif
22
23namespace plask {
24
26struct OmpLockState {};
27
28#if defined(OPENMP_FOUND) || defined(DOXYGEN)
29
31struct OmpEnv {
32 virtual ~OmpEnv() = default;
33 virtual void enable() = 0;
34 virtual void disable() = 0;
35};
36
42struct OmpEnabler {
43 PLASK_API static OmpEnv* env;
44
45 OmpEnabler() {
46 if (env) env->enable();
47 }
48
49 ~OmpEnabler() {
50 if (env) env->disable();
51 }
52
53 inline operator bool() const { return true; } // so that it can be used in an `if` statement
54};
55
56# ifdef _MSC_VER
57# define PLASK_OMP_PARALLEL \
58 if (plask::OmpEnabler omp_enabler{}) __pragma(omp parallel)
59# define PLASK_OMP_PARALLEL_FOR \
60 if (plask::OmpEnabler omp_enabler{}) __pragma(omp parallel for)
61# define PLASK_OMP_PARALLEL_FOR_1 \
62 if (plask::OmpEnabler omp_enabler{}) __pragma(omp parallel for schedule(dynamic,1))
63# else
64# define PLASK_OMP_PARALLEL \
65 if (plask::OmpEnabler omp_enabler{}) _Pragma("omp parallel")
66# define PLASK_OMP_PARALLEL_FOR \
67 if (plask::OmpEnabler omp_enabler{}) _Pragma("omp parallel for")
68# define PLASK_OMP_PARALLEL_FOR_1 \
69 if (plask::OmpEnabler omp_enabler{}) _Pragma("omp parallel for schedule(dynamic,1)")
70# endif
71
73struct OmpLock {
74 OmpLock(const OmpLock&) = delete;
75 OmpLock& operator=(const OmpLock&) = delete;
76 OmpLock(OmpLock&&) = delete;
77 OmpLock& operator=(OmpLock&&) = delete;
78
79 OmpLock() {}
80 virtual ~OmpLock() {}
81
82 virtual OmpLockState* lock() = 0;
83 virtual void unlock(OmpLockState*) = 0;
84};
85
87class OmpNestedLock : public OmpLock {
88 omp_nest_lock_t lck;
89
90 public:
91 OmpNestedLock() { omp_init_nest_lock(&lck); }
92 ~OmpNestedLock() { omp_destroy_nest_lock(&lck); }
93 OmpLockState* lock() override { omp_set_nest_lock(&lck); return nullptr; }
94 void unlock(OmpLockState*) override { omp_unset_nest_lock(&lck); }
95};
96
98class OmpSingleLock : public OmpLock {
99 omp_lock_t lck;
100
101 public:
102 OmpSingleLock() { omp_init_lock(&lck); }
103 ~OmpSingleLock() { omp_destroy_lock(&lck); }
104 OmpLockState* lock() override { omp_set_lock(&lck); return nullptr; }
105 void unlock(OmpLockState*) override { omp_unset_lock(&lck); }
106};
107
109class OmpLockGuard {
110 OmpLock* lock;
111 OmpLockState* state;
112
113 public:
114 OmpLockGuard() : lock(nullptr) {}
115
120 OmpLockGuard(OmpLock& lock) : lock(&lock) { state = lock.lock(); }
121
123 OmpLockGuard(OmpLockGuard&& orig) : lock(orig.lock) { orig.lock = nullptr; };
124
127 if (lock) lock->unlock(state);
128 lock = orig.lock;
129 state = orig.state;
130 orig.lock = nullptr;
131 return *this;
132 }
133
134 OmpLockGuard(const OmpLockGuard&) = delete;
135 OmpLockGuard& operator=(const OmpLockGuard&) = delete;
136
138 ~OmpLockGuard() {
139 if (lock) lock->unlock(state);
140 }
141};
142
143#else
144
145struct OmpEnabler {};
146
147# define PLASK_OMP_PARALLEL
148# define PLASK_OMP_PARALLEL_FOR
149# define PLASK_OMP_PARALLEL_FOR_1
150
151// Empty placeholder
152struct OmpLock {
153 OmpLock(const OmpLock&) = delete;
154 OmpLock& operator=(const OmpLock&) = delete;
155 OmpLock(OmpLock&&) = delete;
157
159
160 inline OmpLockState* lock() { return nullptr; }
161 inline void unlock(OmpLockState*) {}
162};
163
164# define OmpNestedLock OmpLock
165# define OmpSingleLock OmpLock
166
167// Empty placeholder
177
178#endif
179
180} // namespace plask
181
182#endif // PLASK__PLASK_PARALLEL_H