Arcane  v3.14.10.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
StdThreadImplementation.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2022 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-2024 */
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 Arccore::Concurrency
32{
33
34/*---------------------------------------------------------------------------*/
35/*---------------------------------------------------------------------------*/
36/*!
37 * \brief Implémentation de ITreadImplementation avec la bibliothèque standard C++.
38 */
39class ARCCORE_CONCURRENCY_EXPORT StdThreadImplementation
42{
44
45 public:
46
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 //cout << "ADD BARRIER N=" << m_current_reached << '\n';
124 if (m_current_reached == m_nb_thread) {
125 m_current_reached = 0;
126 is_last = true;
127 //cout << "BROADCAST BARRIER N=" << m_current_reached << '\n';
128 m_wait.notify_all();
129 }
130 else
131 m_wait.wait(lk);
132 }
133 return is_last;
134 }
135
136 private:
137
138 std::mutex m_wait_mutex;
139 std::condition_variable m_wait;
140 Integer m_nb_thread = 0;
141 Integer m_current_reached = 0;
142};
143
144/*---------------------------------------------------------------------------*/
145/*---------------------------------------------------------------------------*/
146
147StdThreadImplementation::
148StdThreadImplementation()
149: m_global_mutex_impl(nullptr)
150{
151}
152
153StdThreadImplementation::
154~StdThreadImplementation()
155{
156 GlobalMutex::destroy();
157 if (m_global_mutex_impl)
158 destroyMutex(m_global_mutex_impl);
159}
160
161void StdThreadImplementation::
162initialize()
163{
164 m_global_mutex_impl = createMutex();
165 GlobalMutex::init(m_global_mutex_impl);
166}
167
168ThreadImpl* StdThreadImplementation::
169createThread(IFunctor* f)
170{
171 return reinterpret_cast<ThreadImpl*>(new std::thread(&_StdStartFunc, f));
172}
173
174void StdThreadImplementation::
175joinThread(ThreadImpl* t)
176{
177 std::thread* tt = reinterpret_cast<std::thread*>(t);
178 tt->join();
179}
180
181void StdThreadImplementation::
182destroyThread(ThreadImpl* t)
183{
184 std::thread* tt = reinterpret_cast<std::thread*>(t);
185 delete tt;
186}
187
188void StdThreadImplementation::
189createSpinLock(Int64* spin_lock_addr)
190{
191 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
192}
193
194void StdThreadImplementation::
195lockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr)
196{
197 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
198}
199
200void StdThreadImplementation::
201unlockSpinLock(Int64* spin_lock_addr, Int64* scoped_spin_lock_addr)
202{
203 ARCCORE_THROW(NotSupportedException, "Spin lock. Use std::atomic_flag instead()");
204}
205
206MutexImpl* StdThreadImplementation::
207createMutex()
208{
209 std::mutex* m = new std::mutex();
210 return reinterpret_cast<MutexImpl*>(m);
211}
212
213void StdThreadImplementation::
214destroyMutex(MutexImpl* mutex)
215{
216 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
217 delete m;
218}
219
220void StdThreadImplementation::
221lockMutex(MutexImpl* mutex)
222{
223 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
224 m->lock();
225}
226
227void StdThreadImplementation::
228unlockMutex(MutexImpl* mutex)
229{
230 std::mutex* m = reinterpret_cast<std::mutex*>(mutex);
231 m->unlock();
232}
233
234Int64 StdThreadImplementation::
235currentThread()
236{
237 Int64 v = std::hash<std::thread::id>{}(std::this_thread::get_id());
238 return v;
239}
240
241IThreadBarrier* StdThreadImplementation::
242createBarrier()
243{
244 return new StdThreadBarrier();
245}
246
247/*---------------------------------------------------------------------------*/
248/*---------------------------------------------------------------------------*/
249
250Ref<IThreadImplementation>
251createStdThreadImplementation()
252{
253 return makeRef<IThreadImplementation>(new Concurrency::StdThreadImplementation());
254}
255
256/*---------------------------------------------------------------------------*/
257/*---------------------------------------------------------------------------*/
258
259} // namespace Arccore::Concurrency
260
261/*---------------------------------------------------------------------------*/
262/*---------------------------------------------------------------------------*/
#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 init(Integer nb_thread) override
Initialise la barrière pour nb_thread.
void destroy() override
Détruit la barrière.
bool wait() override
Bloque et attend que tous les threads appellent cette méthode.
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.
Definition Mutex.cc:63
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.
Int32 Integer
Type représentant un entier.
std::int64_t Int64
Type entier signé sur 64 bits.