14#include "arccore/base/NotImplementedException.h"
15#include "arccore/base/IFunctor.h"
17#include "arccore/base/NotSupportedException.h"
20#include "arccore/concurrency/internal/ConcurrencyGlobalInternal.h"
21#include "arccore/concurrency/IThreadBarrier.h"
22#include "arccore/concurrency/Mutex.h"
25#include <condition_variable>
32namespace Arcane::Concurrency
40class ARCCORE_CONCURRENCY_EXPORT StdThreadImplementation
48 explicit StdThreadImplementation(
bool use_legacy_barrier);
49 ~StdThreadImplementation()
override;
53 void initialize()
override;
57 ThreadImpl* createThread(
IFunctor* f)
override;
58 void joinThread(ThreadImpl* t)
override;
59 void destroyThread(ThreadImpl* t)
override;
61 void createSpinLock(
Int64* spin_lock_addr)
override;
62 void lockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override;
63 void unlockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override;
65 MutexImpl* createMutex()
override;
66 void destroyMutex(MutexImpl*)
override;
67 void lockMutex(MutexImpl* mutex)
override;
68 void unlockMutex(MutexImpl* mutex)
override;
70 Int64 currentThread()
override;
76 void addReference()
override { ReferenceCounterImpl::addReference(); }
77 void removeReference()
override { ReferenceCounterImpl::removeReference(); }
81 MutexImpl* m_global_mutex_impl =
nullptr;
82 bool m_use_legacy_barrier =
false;
90 void* _StdStartFunc(
void* f)
113 m_nb_thread = nb_thread;
114 m_current_reached = 0;
120 m_current_reached = 0;
126 std::unique_lock<std::mutex> lk(m_wait_mutex);
128 Int32 generation = m_generation;
130 if (m_current_reached == m_nb_thread) {
132 m_current_reached = 0;
137 while (generation == m_generation)
143 std::mutex m_wait_mutex;
144 std::condition_variable m_wait;
147 Int32 m_generation = 0;
162 void operator()()
const noexcept { }
173 m_barrier =
new std::barrier<NullFunc>(nb_thread);
184 m_barrier->arrive_and_wait();
189 std::barrier<NullFunc>* m_barrier =
nullptr;
195StdThreadImplementation::
196StdThreadImplementation(
bool use_legacy_barrier)
197: m_use_legacy_barrier(use_legacy_barrier)
201StdThreadImplementation::
202~StdThreadImplementation()
204 GlobalMutex::destroy();
205 if (m_global_mutex_impl)
206 destroyMutex(m_global_mutex_impl);
209void StdThreadImplementation::
212 m_global_mutex_impl = createMutex();
216ThreadImpl* StdThreadImplementation::
217createThread(IFunctor* f)
219 return reinterpret_cast<ThreadImpl*
>(
new std::thread(&_StdStartFunc, f));
222void StdThreadImplementation::
223joinThread(ThreadImpl* t)
225 std::thread* tt =
reinterpret_cast<std::thread*
>(t);
229void StdThreadImplementation::
230destroyThread(ThreadImpl* t)
232 std::thread* tt =
reinterpret_cast<std::thread*
>(t);
236void StdThreadImplementation::
237createSpinLock(
Int64* spin_lock_addr)
239 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
242void StdThreadImplementation::
243lockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
245 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
248void StdThreadImplementation::
249unlockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
251 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
254MutexImpl* StdThreadImplementation::
257 std::mutex* m =
new std::mutex();
258 return reinterpret_cast<MutexImpl*
>(m);
261void StdThreadImplementation::
262destroyMutex(MutexImpl* mutex)
264 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
268void StdThreadImplementation::
269lockMutex(MutexImpl* mutex)
271 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
275void StdThreadImplementation::
276unlockMutex(MutexImpl* mutex)
278 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
282Int64 StdThreadImplementation::
285 Int64 v = std::hash<std::thread::id>{}(std::this_thread::get_id());
289IThreadBarrier* StdThreadImplementation::
292 if (m_use_legacy_barrier)
293 return new LegacyStdThreadBarrier();
294 return new StdThreadBarrier();
300Ref<IThreadImplementation>
301createStdThreadImplementation()
306Ref<IThreadImplementation>
307createLegacyStdThreadImplementation()
#define ARCCORE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCCORE_CHECK_POINTER(ptr)
Macro retournant le pointeur ptr s'il est non nul ou lancant une exception s'il est nul.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro pour définir les méthodes gérant les compteurs de référence.
Gestion des références à une classe C++.
Implémentation d'une barrière.
void init(Integer nb_thread) override
Initialise la barrière pour nb_thread.
void wait() override
Bloque et attend que tous les threads appellent cette méthode.
void destroy() override
Détruit la barrière.
Implémentation d'une barrière via std::barrier.
void destroy() override
Détruit la barrière.
void wait() override
Bloque et attend que tous les threads appellent cette méthode.
void init(Integer nb_thread) override
Initialise la barrière pour nb_thread.
Implémentation de ITreadImplementation avec la bibliothèque standard C++.
static void init(MutexImpl *p)
Initialise le mutex global. Interne a Arccore. Doit être alloué par new.
virtual void executeFunctor()=0
Exécute la méthode associé
Interface d'une barrière entre threads.
Interface d'un service implémentant le support des threads.
Implémentation thread-safe d'un compteur de référence.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.