@@ -103,72 +103,6 @@ namespace
103
103
104
104
using supported_mutex_types = std::tuple<std::mutex, std::shared_mutex, std::recursive_mutex>;
105
105
106
- template <mamba::util::Mutex M>
107
- auto test_concurrent_increment (
108
- std::invocable<mamba::util::synchronized_value<ValueType, M>&> auto increment_task
109
- )
110
- {
111
- static constexpr auto arbitrary_number_of_executing_threads = 512 ;
112
-
113
- mamba::util::synchronized_value<ValueType, M> current_value;
114
- static constexpr int expected_result = arbitrary_number_of_executing_threads;
115
-
116
- std::atomic<bool > run_tasks = false ; // used to launch tasks about the same time, simpler
117
- // than condition_variable
118
- std::vector<std::future<void >> tasks;
119
-
120
- // Launch the reading and writing tasks (maybe threads, depends on how async is implemented)
121
- for (int i = 0 ; i < expected_result * 2 ; ++i)
122
- {
123
- if (i % 2 ) // intertwine reading and writing tasks
124
- {
125
- // add writing task
126
- tasks.push_back (std::async (
127
- std::launch::async,
128
- [&, increment_task]
129
- {
130
- // don't actually run until we get the green light
131
- mambatests::wait_condition ([&] { return run_tasks == true ; });
132
- increment_task (current_value);
133
- }
134
- ));
135
- }
136
- else
137
- {
138
- // add reading task
139
- tasks.push_back (std::async (
140
- std::launch::async,
141
- [&]
142
- {
143
- // don't actually run until we get the green light
144
- mambatests::wait_condition ([&] { return run_tasks == true ; });
145
- const auto & readonly_value = std::as_const (current_value);
146
- static constexpr auto arbitrary_read_count = 100 ;
147
- long long sum = 0 ;
148
- for (int c = 0 ; c < arbitrary_read_count; ++c)
149
- {
150
- sum += readonly_value->x ; // TODO: also try to mix reading and writing
151
- // using different kinds of access
152
- std::this_thread::yield (); // for timing randomness and limit
153
- // over-exhaustion
154
- }
155
- REQUIRE (sum != 0 ); // It is possible but extremely unlikely that all
156
- // reading tasks will read before any writing tasks.
157
- }
158
- ));
159
- }
160
- }
161
-
162
- run_tasks = true ; // green light, tasks will run probably concurrently, worse case in
163
- // unpredictable order
164
- for (auto & task : tasks)
165
- {
166
- task.wait (); // wait all to be finished
167
- }
168
-
169
- REQUIRE (current_value->x == expected_result);
170
- }
171
-
172
106
template <mamba::util::Mutex MutexType>
173
107
void test_synchronized_value_basics ()
174
108
{
@@ -318,6 +252,72 @@ namespace
318
252
REQUIRE (values == initial_values);
319
253
}
320
254
255
+ template <mamba::util::Mutex M>
256
+ auto test_concurrent_increment (
257
+ std::invocable<mamba::util::synchronized_value<ValueType, M>&> auto increment_task
258
+ )
259
+ {
260
+ static constexpr auto arbitrary_number_of_executing_threads = 512 ;
261
+
262
+ mamba::util::synchronized_value<ValueType, M> current_value;
263
+ static constexpr int expected_result = arbitrary_number_of_executing_threads;
264
+
265
+ std::atomic<bool > run_tasks = false ; // used to launch tasks about the same time, simpler
266
+ // than condition_variable
267
+ std::vector<std::future<void >> tasks;
268
+
269
+ // Launch the reading and writing tasks (maybe threads, depends on how async is implemented)
270
+ for (int i = 0 ; i < expected_result * 2 ; ++i)
271
+ {
272
+ if (i % 2 ) // intertwine reading and writing tasks
273
+ {
274
+ // add writing task
275
+ tasks.push_back (std::async (
276
+ std::launch::async,
277
+ [&, increment_task]
278
+ {
279
+ // don't actually run until we get the green light
280
+ mambatests::wait_condition ([&] { return run_tasks == true ; });
281
+ increment_task (current_value);
282
+ }
283
+ ));
284
+ }
285
+ else
286
+ {
287
+ // add reading task
288
+ tasks.push_back (std::async (
289
+ std::launch::async,
290
+ [&]
291
+ {
292
+ // don't actually run until we get the green light
293
+ mambatests::wait_condition ([&] { return run_tasks == true ; });
294
+ const auto & readonly_value = std::as_const (current_value);
295
+ static constexpr auto arbitrary_read_count = 100 ;
296
+ long long sum = 0 ;
297
+ for (int c = 0 ; c < arbitrary_read_count; ++c)
298
+ {
299
+ sum += readonly_value->x ; // TODO: also try to mix reading and writing
300
+ // using different kinds of access
301
+ std::this_thread::yield (); // for timing randomness and limit
302
+ // over-exhaustion
303
+ }
304
+ REQUIRE (sum != 0 ); // It is possible but extremely unlikely that all
305
+ // reading tasks will read before any writing tasks.
306
+ }
307
+ ));
308
+ }
309
+ }
310
+
311
+ run_tasks = true ; // green light, tasks will run probably concurrently, worse case in
312
+ // unpredictable order
313
+ for (auto & task : tasks)
314
+ {
315
+ task.wait (); // wait all to be finished
316
+ }
317
+
318
+ REQUIRE (current_value->x == expected_result);
319
+ }
320
+
321
321
// Factorized thread-safe direct_access test
322
322
template <mamba::util::Mutex MutexType>
323
323
void test_synchronized_value_threadsafe_direct_access ()
0 commit comments