Arcane  v3.15.0.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
TestConcurrency.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2024 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#include <gtest/gtest.h>
8
9#include "arccore/base/PlatformUtils.h"
10#include "arccore/base/Functor.h"
11#include "arccore/base/Ref.h"
12
13#include "arccore/concurrency/SpinLock.h"
14#include "arccore/concurrency/Mutex.h"
15#include "arccore/concurrency/IThreadBarrier.h"
16
17using namespace Arccore;
18
19/*---------------------------------------------------------------------------*/
20/*---------------------------------------------------------------------------*/
21
23{
24 public:
25
26 MyThread() = default;
27 explicit MyThread(IFunctor* f)
28 {
29 create(f);
30 }
31 ~MyThread()
32 {
33 if (m_thread)
34 Concurrency::getThreadImplementation()->destroyThread(m_thread);
35 }
36 void create(IFunctor* f)
37 {
38 m_functor = f;
39 m_thread = Concurrency::getThreadImplementation()->createThread(f);
40 }
41 void join()
42 {
43 Concurrency::getThreadImplementation()->joinThread(m_thread);
44 }
45
46 public:
47
48 IFunctor* m_functor = nullptr;
49 ThreadImpl* m_thread = nullptr;
50};
51
52/*---------------------------------------------------------------------------*/
53/*---------------------------------------------------------------------------*/
54
56{
57 public:
58
60 {
61 }
62
63 explicit TestSpinLock1(SpinLock::eMode mode)
64 : m_lock(mode)
65 {
66 }
67
68 void exec()
69 {
71 const Int32 nb_iter = 70;
72 const Int32 nb_thread = 10;
73 for (Integer i = 0; i < nb_iter; ++i) {
74 FunctorT<TestSpinLock1> f1(this, &TestSpinLock1::_F1);
75 std::vector<MyThread> threads(nb_thread);
76 for (Integer j = 0; j < nb_thread; ++j)
77 threads[j].create(&f1);
78 for (Integer j = 0; j < nb_thread; ++j)
79 threads[j].join();
80 }
82 std::cout << "Test1 spin_time=" << (v2 - v1) << " count2=" << m_count2 << " count3=" << m_count3 << "\n";
83 Int64 expected_count3 = nb_iter * m_nb_sub_iter * nb_thread;
84 Int64 expected_count2 = 10 * expected_count3 + (expected_count3 * (expected_count3 + 1)) / 2;
85 std::cout << " expected_count2=" << expected_count2 << " expected_count3=" << expected_count3 << "\n";
86 ASSERT_EQ(m_count2, expected_count2);
87 ASSERT_EQ(m_count3, expected_count3);
88 }
89 void _F1()
90 {
91 for (Int32 i = 0; i < m_nb_sub_iter; ++i) {
92 ++m_count;
93 {
94 SpinLock::ScopedLock sl(m_lock);
95 ++m_count3;
96 m_count2 += 10;
97 m_count2 += m_count3;
98 }
99 }
100 }
101 SpinLock m_lock;
102 std::atomic<Int64> m_count = 0;
103 Int64 m_count2 = 0;
104 Int64 m_count3 = 0;
105 Int32 m_nb_sub_iter = 1000;
106};
107
108/*---------------------------------------------------------------------------*/
109/*---------------------------------------------------------------------------*/
110
112{
113 public:
114
116 : m_thread_implementation(Concurrency::getThreadImplementation())
117 {
118 }
119
120 void exec()
121 {
123 const Int32 nb_iter = 70;
124 const Int32 nb_thread = 10;
125 m_thread_barrier = m_thread_implementation->createBarrier();
126 m_thread_barrier->init(nb_thread);
127 for (Integer i = 0; i < nb_iter; ++i) {
128 FunctorT<TestMutexLock1> f1(this, &TestMutexLock1::_F1);
129 std::vector<MyThread> threads(nb_thread);
130 for (Integer j = 0; j < nb_thread; ++j)
131 threads[j].create(&f1);
132 for (Integer j = 0; j < nb_thread; ++j)
133 threads[j].join();
134 m_do_print_id = false;
135 }
137 std::cout << "Test1 spin_time=" << (v2 - v1) << " count2=" << m_count2 << " count3=" << m_count3 << "\n";
138 Int64 expected_count3 = nb_iter * m_nb_sub_iter * nb_thread;
139 Int64 expected_count2 = 10 * expected_count3 + (expected_count3 * (expected_count3 + 1)) / 2;
140 std::cout << " expected_count2=" << expected_count2 << " expected_count3=" << expected_count3 << "\n";
141 ASSERT_EQ(m_count2, expected_count2);
142 ASSERT_EQ(m_count3, expected_count3);
143 m_thread_barrier->destroy();
144 }
145 void _F1()
146 {
147 for (Int32 i = 0; i < m_nb_sub_iter; ++i) {
148 ++m_count;
149 {
150 Mutex::ScopedLock sl(m_mutex);
151 ++m_count3;
152 m_count2 += 10;
153 m_count2 += m_count3;
154 }
155 }
156 m_thread_barrier->wait();
157 if (m_do_print_id) {
158 std::ostringstream ostr;
159 ostr << "THREAD_ID=" << m_thread_implementation->currentThread() << "\n";
160 std::cout << ostr.str();
161 }
162 }
163 IThreadImplementation* m_thread_implementation = nullptr;
164 Mutex m_mutex;
165 IThreadBarrier* m_thread_barrier = nullptr;
166 std::atomic<Int64> m_count = 0;
167 Int64 m_count2 = 0;
168 Int64 m_count3 = 0;
169 Int32 m_nb_sub_iter = 1000;
170 bool m_do_print_id = true;
171};
172
173namespace
174{
175void _doSpinLock()
176{
177
178 {
179 TestSpinLock1 test1;
180 test1.exec();
181 }
182 {
183 TestSpinLock1 test2(SpinLock::eMode::FullSpin);
184 test2.exec();
185 }
186 {
187 TestSpinLock1 test3(SpinLock::eMode::SpinAndMutex);
188 test3.exec();
189 }
190}
191void _doMutexLock()
192{
193
194 {
195 TestMutexLock1 test1;
196 test1.exec();
197 }
198}
199} // namespace
200
201TEST(Concurrency, GlibSpinLock)
202{
203 Ref<IThreadImplementation> timpl(Concurrency::createGlibThreadImplementation());
204 Concurrency::setThreadImplementation(timpl.get());
205 _doSpinLock();
206 Concurrency::setThreadImplementation(nullptr);
207}
208
209TEST(Concurrency, StdSpinLock)
210{
211 Ref<IThreadImplementation> timpl(Concurrency::createStdThreadImplementation());
212 Concurrency::setThreadImplementation(timpl.get());
213 _doSpinLock();
214 Concurrency::setThreadImplementation(nullptr);
215}
216
217TEST(Concurrency, GlibMutexLock)
218{
219 Ref<IThreadImplementation> timpl(Concurrency::createGlibThreadImplementation());
220 Concurrency::setThreadImplementation(timpl.get());
221 _doMutexLock();
222 Concurrency::setThreadImplementation(nullptr);
223}
224
225TEST(Concurrency, StdMutexLock)
226{
227 Ref<IThreadImplementation> timpl(Concurrency::createStdThreadImplementation());
228 Concurrency::setThreadImplementation(timpl.get());
229 _doMutexLock();
230 Concurrency::setThreadImplementation(nullptr);
231}
232
233/*---------------------------------------------------------------------------*/
234/*---------------------------------------------------------------------------*/
Gestion des références à une classe C++.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:149
Functor associé à une méthode d'une classe T.
virtual void destroy()=0
Détruit la barrière.
virtual bool wait()=0
Bloque et attend que tous les threads appellent cette méthode.
virtual void init(Integer nb_thread)=0
Initialise la barrière pour nb_thread.
Interface d'un service implémentant le support des threads.
Référence à une instance.
eMode
Mode du spinlock. Le défaut est 'Auto'.
ARCCORE_BASE_EXPORT Real getRealTime()
Temps Real utilisé en secondes.
Espace de nom de Arccore.
Definition ArcaneTypes.h:24
Int32 Integer
Type représentant un entier.
std::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.