14#include "arcane/utils/IThreadImplementationService.h"
15#include "arcane/utils/IThreadBarrier.h"
16#include "arcane/utils/NotImplementedException.h"
17#include "arcane/utils/IFunctor.h"
18#include "arcane/utils/Mutex.h"
19#include "arcane/utils/PlatformUtils.h"
20#include "arcane/utils/internal/DependencyInjection.h"
22#include "arcane/FactoryService.h"
23#include "arcane/Concurrency.h"
25#include "arcane/parallel/thread/ArcaneThreadMisc.h"
28#if TBB_VERSION_MAJOR >= 2020
29#define ARCANE_TBB_USE_STDTHREAD
32#include <tbb/tbb_thread.h>
33#include <tbb/atomic.h>
49#ifdef ARCANE_TBB_USE_STDTHREAD
51typedef std::thread ThreadType;
56inline Int64 arcaneGetThisThreadId()
58 Int64 v = std::hash<std::thread::id>{}(std::this_thread::get_id());
65#if defined(_WIN32) || defined(_WIN64)
72typedef tbb::tbb_thread ThreadType;
73inline Int64 arcaneGetThisThreadId()
75 ThreadType::id i = tbb::this_tbb_thread::get_id();
114 m_nb_thread = nb_thread;
115 m_nb_thread_finished = 0;
121 Int32 ts = m_timestamp;
122 int remaining_thread = m_nb_thread - m_nb_thread_finished.fetch_add(1) - 1;
123 if (remaining_thread > 0) {
126 while (m_timestamp==ts){
140 m_nb_thread_finished = 0;
146 std::atomic<Int32> m_nb_thread_finished;
147 std::atomic<Int32> m_timestamp;
153extern "C" IThreadBarrier*
154createGlibThreadBarrier();
161class TBBThreadImplementation
165 ARCCORE_DEFINE_REFERENCE_COUNTED_INCLASS_METHODS();
167 void addReference()
override { ReferenceCounterImpl::addReference(); }
168 void removeReference()
override { ReferenceCounterImpl::removeReference(); }
176 void operator()() { m_f->executeFunctor(); }
182 TBBThreadImplementation()
183 : m_use_tbb_barrier(false)
184 , m_global_mutex_impl(nullptr)
187 m_use_tbb_barrier =
true;
188 m_std_thread_implementation = Arccore::Concurrency::createStdThreadImplementation();
194 GlobalMutex::destroy();
195 if (m_global_mutex_impl)
196 this->destroyMutex(m_global_mutex_impl);
205 void initialize()
override
207 m_global_mutex_impl = createMutex();
213 ThreadImpl* createThread(IFunctor* f)
override
215 return reinterpret_cast<ThreadImpl*
>(
new ThreadType(
StartFunc(f)));
217 void joinThread(ThreadImpl* t)
override
219 ThreadType* tt =
reinterpret_cast<ThreadType*
>(t);
222 void destroyThread(ThreadImpl* t)
override
224 ThreadType* tt =
reinterpret_cast<ThreadType*
>(t);
228 void createSpinLock(
Int64* spin_lock_addr)
override
230 void* addr = spin_lock_addr;
231 new (addr) tbb::spin_mutex();
233 void lockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override
235 tbb::spin_mutex* s =
reinterpret_cast<tbb::spin_mutex*
>(spin_lock_addr);
236 tbb::spin_mutex::scoped_lock* sl =
new (scoped_spin_lock_addr) tbb::spin_mutex::scoped_lock();
239 void unlockSpinLock(
Int64* spin_lock_addr,
Int64* scoped_spin_lock_addr)
override
241 ARCANE_UNUSED(spin_lock_addr);
242 tbb::spin_mutex::scoped_lock* s =
reinterpret_cast<tbb::spin_mutex::scoped_lock*
>(scoped_spin_lock_addr);
247 MutexImpl* createMutex()
override
249 TBBMutexImpl* m =
new TBBMutexImpl();
250 return reinterpret_cast<MutexImpl*
>(m);
252 void destroyMutex(MutexImpl* mutex)
override
254 TBBMutexImpl* tm =
reinterpret_cast<TBBMutexImpl*
>(mutex);
257 void lockMutex(MutexImpl* mutex)
override
259 TBBMutexImpl* tm =
reinterpret_cast<TBBMutexImpl*
>(mutex);
262 void unlockMutex(MutexImpl* mutex)
override
264 TBBMutexImpl* tm =
reinterpret_cast<TBBMutexImpl*
>(mutex);
268 Int64 currentThread()
override
270 Int64 v = arcaneGetThisThreadId();
274 IThreadBarrier* createBarrier()
override
280 if (m_use_tbb_barrier)
281 return new TBBBarrier();
282 return m_std_thread_implementation->createBarrier();
287 bool m_use_tbb_barrier;
288 MutexImpl* m_global_mutex_impl;
289 Ref<IThreadImplementation> m_std_thread_implementation;
295class TBBThreadImplementationService
301 TBBThreadImplementationService() =
default;
322 DependencyInjection::ProviderProperty(
"TBBThreadImplementationService"),
324 ARCANE_DI_EMPTY_CONSTRUCTOR());
#define ARCANE_SERVICE_INTERFACE(ainterface)
Macro pour déclarer une interface lors de l'enregistrement d'un service.
static void init(MutexImpl *p)
Initialise le mutex global. Interne a Arccore. Doit être alloué par new.
Interface d'une barrière entre threads.
Interface d'un service de gestion des threads.
Interface d'un service implémentant le support des threads.
Référence à une instance.
Implémentation thread-safe d'un compteur de référence.
Structure contenant les informations pour créer un service.
Propriétés de création d'un service.
virtual void destroy()
Détruit la barrière.
virtual bool wait()
Bloque et attend que tous les threads appellent cette méthode.
virtual void init(Integer nb_thread)
Initialise la barrière pour nb_thread.
Implémentation des threads utilisant TBB (Intel Threads Building Blocks).
#define ARCANE_REGISTER_SERVICE(aclass, a_service_property,...)
Macro pour enregistrer un service.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
std::int64_t Int64
Type entier signé sur 64 bits.
void arcaneDoCPUPause(Int32 count)
Utilise l'instruction 'pause' du CPU si possible.
Int32 Integer
Type représentant un entier.
@ ST_Application
Le service s'utilise au niveau de l'application.
auto makeRef(InstanceType *t) -> Ref< InstanceType >
Créé une référence sur un pointeur.
std::int32_t Int32
Type entier signé sur 32 bits.