Arcane  v3.16.6.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
StdThreadImplementation.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* StdThreadImplementation.cc (C) 2000-2025 */
9/* */
10/* Implémentation des threads utilisant la bibliothèque standard C++. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arccore/base/NotImplementedException.h"
15#include "arccore/base/IFunctor.h"
17#include "arccore/base/NotSupportedException.h"
18#include "arccore/base/Ref.h"
19
20#include "arccore/concurrency/IThreadBarrier.h"
21#include "arccore/concurrency/Mutex.h"
22
23#include <new>
24#include <thread>
25#include <condition_variable>
26#include <mutex>
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
31namespace Arcane::Concurrency
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
39class ARCCORE_CONCURRENCY_EXPORT StdThreadImplementation
42{
44
45 public:
46
47 StdThreadImplementation();
48 ~StdThreadImplementation() override;
49
50 public:
51
52 void initialize() override;
53
54 public:
55
56 ThreadImpl* createThread(IFunctor* f) override;
57 void joinThread(ThreadImpl* t) override;
58 void destroyThread(ThreadImpl* t) override;
59
60 void createSpinLock(Int64* spin_lock_addr) override;
61 void lockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr) override;
62 void unlockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr) override;
63
64 MutexImpl* createMutex() override;
65 void destroyMutex(MutexImpl*) override;
66 void lockMutex(MutexImpl* mutex) override;
67 void unlockMutex(MutexImpl* mutex) override;
68
69 Int64 currentThread() override;
70
71 IThreadBarrier* createBarrier() override;
72
73 public:
74
75 void addReference() override { ReferenceCounterImpl::addReference(); }
76 void removeReference() override { ReferenceCounterImpl::removeReference(); }
77
78 private:
79
80 MutexImpl* m_global_mutex_impl = nullptr;
81};
82
83/*---------------------------------------------------------------------------*/
84/*---------------------------------------------------------------------------*/
85
86namespace
87{
88 void* _StdStartFunc(void* f)
89 {
90 IFunctor* ff = reinterpret_cast<IFunctor*>(f);
91 ff->executeFunctor();
92 return 0;
93 }
94} // namespace
95
96/*---------------------------------------------------------------------------*/
97/*---------------------------------------------------------------------------*/
98
100: public IThreadBarrier
101{
102 public:
103
104 void init(Integer nb_thread) override
105 {
106 m_nb_thread = nb_thread;
107 m_current_reached = 0;
108 }
109
110 void destroy() override
111 {
112 m_nb_thread = 0;
113 m_current_reached = 0;
114 delete this;
115 }
116
117 bool wait() override
118 {
119 bool is_last = false;
120 {
121 std::unique_lock<std::mutex> lk(m_wait_mutex);
122 ++m_current_reached;
123 Int32 generation = m_generation;
124 //cout << "ADD BARRIER N=" << m_current_reached << '\n';
125 if (m_current_reached == m_nb_thread) {
126 ++m_generation;
127 m_current_reached = 0;
128 is_last = true;
129 //cout << "BROADCAST BARRIER N=" << m_current_reached << '\n';
130 lk.unlock();
131 m_wait.notify_all();
132 }
133 while (generation == m_generation)
134 m_wait.wait(lk);
135 }
136 return is_last;
137 }
138
139 private:
140
141 std::mutex m_wait_mutex;
142 std::condition_variable m_wait;
143 Integer m_nb_thread = 0;
144 Integer m_current_reached = 0;
145 Int32 m_generation = 0;
146};
147
148/*---------------------------------------------------------------------------*/
149/*---------------------------------------------------------------------------*/
150
151StdThreadImplementation::
152StdThreadImplementation()
153: m_global_mutex_impl(nullptr)
154{
155}
156
157StdThreadImplementation::
158~StdThreadImplementation()
159{
160 GlobalMutex::destroy();
161 if (m_global_mutex_impl)
162 destroyMutex(m_global_mutex_impl);
163}
164
165void StdThreadImplementation::
166initialize()
167{
168 m_global_mutex_impl = createMutex();
169 GlobalMutex::init(m_global_mutex_impl);
170}
171
172ThreadImpl* StdThreadImplementation::
173createThread(IFunctor* f)
174{
175 return reinterpret_cast<ThreadImpl*>(new std::thread(&_StdStartFunc, f));
176}
177
178void StdThreadImplementation::
179joinThread(ThreadImpl* t)
180{
181 std::thread* tt = reinterpret_cast<std::thread*>(t);
182 tt->join();
183}
184
185void StdThreadImplementation::
186destroyThread(ThreadImpl* t)
187{
188 std::thread* tt = reinterpret_cast<std::thread*>(t);
189 delete tt;
190}
191
192void StdThreadImplementation::
193createSpinLock(Int64* spin_lock_addr)
194{
195 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
196}
197
198void StdThreadImplementation::
199lockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr)
200{
201 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
202}
203
204void StdThreadImplementation::
205unlockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr)
206{
207 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
208}
209
210MutexImpl* StdThreadImplementation::
211createMutex()
212{
213 std::mutex* m = new std::mutex();
214 return reinterpret_cast<MutexImpl*>(m);
215}
216
217void StdThreadImplementation::
218destroyMutex(MutexImpl* mutex)
219{
220 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
221 delete m;
222}
223
224void StdThreadImplementation::
225lockMutex(MutexImpl* mutex)
226{
227 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
228 m->lock();
229}
230
231void StdThreadImplementation::
232unlockMutex(MutexImpl* mutex)
233{
234 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
235 m->unlock();
236}
237
238Int64 StdThreadImplementation::
239currentThread()
240{
241 Int64 v = std::hash<std::thread::id>{}(std::this_thread::get_id());
242 return v;
243}
244
245IThreadBarrier* StdThreadImplementation::
246createBarrier()
247{
248 return new StdThreadBarrier();
249}
250
251/*---------------------------------------------------------------------------*/
252/*---------------------------------------------------------------------------*/
253
254Ref<IThreadImplementation>
255createStdThreadImplementation()
256{
257 return makeRef<IThreadImplementation>(new Concurrency::StdThreadImplementation());
258}
259
260/*---------------------------------------------------------------------------*/
261/*---------------------------------------------------------------------------*/
262
263} // namespace Arccore::Concurrency
264
265/*---------------------------------------------------------------------------*/
266/*---------------------------------------------------------------------------*/
#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++.
void destroy() override
Détruit la barrière.
void init(Integer nb_thread) override
Initialise la barrière pour nb_thread.
bool wait() override
Bloque et attend que tous les threads appellent cette méthode.
static void init(MutexImpl *p)
Initialise le mutex global. Interne a Arccore. Doit être alloué par new.
Definition Mutex.cc:60
virtual void executeFunctor()=0
Exécute la méthode associé
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.