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
41class ARCCORE_CONCURRENCY_EXPORT StdThreadImplementation
49 explicit StdThreadImplementation(
bool use_legacy_barrier);
50 ~StdThreadImplementation()
override;
54 void initialize()
override;
58 ThreadImpl* createThread(
IFunctor* f)
override;
59 void joinThread(ThreadImpl* t)
override;
60 void destroyThread(ThreadImpl* t)
override;
62 void createSpinLock(
Int64* spin_lock_addr)
override;
63 void lockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override;
64 void unlockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override;
66 MutexImpl* createMutex()
override;
67 void destroyMutex(MutexImpl*)
override;
68 void lockMutex(MutexImpl* mutex)
override;
69 void unlockMutex(MutexImpl* mutex)
override;
71 Int64 currentThread()
override;
77 void addReference()
override { ReferenceCounterImpl::addReference(); }
78 void removeReference()
override { ReferenceCounterImpl::removeReference(); }
82 MutexImpl* m_global_mutex_impl =
nullptr;
83 bool m_use_legacy_barrier =
false;
91 void* _StdStartFunc(
void* f)
115 m_nb_thread = nb_thread;
116 m_current_reached = 0;
122 m_current_reached = 0;
128 std::unique_lock<std::mutex> lk(m_wait_mutex);
130 Int32 generation = m_generation;
132 if (m_current_reached == m_nb_thread) {
134 m_current_reached = 0;
139 while (generation == m_generation)
145 std::mutex m_wait_mutex;
146 std::condition_variable m_wait;
149 Int32 m_generation = 0;
165 void operator()()
const noexcept { }
176 m_barrier =
new std::barrier<NullFunc>(nb_thread);
187 m_barrier->arrive_and_wait();
192 std::barrier<NullFunc>* m_barrier =
nullptr;
198StdThreadImplementation::
199StdThreadImplementation(
bool use_legacy_barrier)
200: m_use_legacy_barrier(use_legacy_barrier)
204StdThreadImplementation::
205~StdThreadImplementation()
207 GlobalMutex::destroy();
208 if (m_global_mutex_impl)
209 destroyMutex(m_global_mutex_impl);
212void StdThreadImplementation::
215 m_global_mutex_impl = createMutex();
219ThreadImpl* StdThreadImplementation::
220createThread(IFunctor* f)
222 return reinterpret_cast<ThreadImpl*
>(
new std::thread(&_StdStartFunc, f));
225void StdThreadImplementation::
226joinThread(ThreadImpl* t)
228 std::thread* tt =
reinterpret_cast<std::thread*
>(t);
232void StdThreadImplementation::
233destroyThread(ThreadImpl* t)
235 std::thread* tt =
reinterpret_cast<std::thread*
>(t);
239void StdThreadImplementation::
240createSpinLock(
Int64* spin_lock_addr)
242 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
245void StdThreadImplementation::
246lockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
248 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
251void StdThreadImplementation::
252unlockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
254 ARCCORE_THROW(NotSupportedException,
"Spin lock. Use std::atomic_flag instead()");
257MutexImpl* StdThreadImplementation::
260 std::mutex* m =
new std::mutex();
261 return reinterpret_cast<MutexImpl*
>(m);
264void StdThreadImplementation::
265destroyMutex(MutexImpl* mutex)
267 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
271void StdThreadImplementation::
272lockMutex(MutexImpl* mutex)
274 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
278void StdThreadImplementation::
279unlockMutex(MutexImpl* mutex)
281 std::mutex* m =
reinterpret_cast<std::mutex*
>(mutex);
285Int64 StdThreadImplementation::
288 Int64 v = std::hash<std::thread::id>{}(std::this_thread::get_id());
292IThreadBarrier* StdThreadImplementation::
295 if (m_use_legacy_barrier)
296 return new LegacyStdThreadBarrier();
297 return new StdThreadBarrier();
303Ref<IThreadImplementation>
304createStdThreadImplementation()
309Ref<IThreadImplementation>
310createLegacyStdThreadImplementation()
#define ARCCORE_THROW(exception_class,...)
Macro to throw an exception with formatting.
#define ARCCORE_CHECK_POINTER(ptr)
Macro that returns the pointer ptr if it is not null or throws an exception if it is null.
#define ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS()
Macro to define methods managing counters of references.
Management of references to a C++ class.
Implementation of a barrier.
void init(Integer nb_thread) override
Initializes the barrier for nb_thread.
void wait() override
Blocks and waits until all threads call this method.
void destroy() override
Destroys the barrier.
Implementation of a barrier using std::barrier.
void destroy() override
Destroys the barrier.
void wait() override
Blocks and waits until all threads call this method.
void init(Integer nb_thread) override
Initializes the barrier for nb_thread.
Implementation of ITreadImplementation using the standard C++ library.
static void init(MutexImpl *p)
Initializes the global mutex. Internal to Arccore. Must be allocated by new.
virtual void executeFunctor()=0
Executes the associated method.
Interface of a barrier between threads.
Interface of a service implementing thread support.
Thread-safe implementation of a reference counter.
std::int64_t Int64
Signed integer type of 64 bits.
Int32 Integer
Type representing an integer.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Creates a reference on a pointer.
std::int32_t Int32
Signed integer type of 32 bits.