| 308 | }; |
| 309 | |
| 310 | command_result sharedsignal (color_ostream &out, vector <string> & parameters) |
| 311 | { |
| 312 | using rng_t = std::linear_congruential_engine<uint32_t, 747796405U, 2891336453U, 0>; |
| 313 | rng_t rng(std::random_device{}()); |
| 314 | size_t count = 10; |
| 315 | if (0 < parameters.size()) { |
| 316 | std::stringstream ss(parameters[0]); |
| 317 | ss >> count; |
| 318 | DEBUG(command, out) << "Parsed " << count |
| 319 | << " from paramters[0] '" << parameters[0] << '\'' << std::endl; |
| 320 | } |
| 321 | |
| 322 | |
| 323 | std::uniform_int_distribution<uint32_t> dis(4096,8192); |
| 324 | out << "Running signal_shared_tag destruction test " |
| 325 | << count << " times" << std::endl; |
| 326 | for (size_t nr = 0; nr < count; ++nr) { |
| 327 | std::array<std::thread,4> t{}; |
| 328 | // Make an object which destruction is protected by std::thread::join() |
| 329 | Connected external{static_cast<int>(t.size())}; |
| 330 | TRACE(command, out) << "begin " << std::endl; |
| 331 | { |
| 332 | int id = 0; |
| 333 | // Make objects that are automatically protected using weak_ptr |
| 334 | // references that are promoted to shared_ptr when Signal is |
| 335 | // accessed. |
| 336 | std::array<shared,4> c = { |
| 337 | std::make_shared<Connected>(id++), |
| 338 | std::make_shared<Connected>(id++), |
| 339 | std::make_shared<Connected>(id++), |
| 340 | std::make_shared<Connected>(id++), |
| 341 | }; |
| 342 | assert(t.size() == c.size()); |
| 343 | for (unsigned i = 1; i < c.size(); ++i) { |
| 344 | c[0]->connect(out, c[0], c[i], i - 1, dis(rng)); |
| 345 | c[i]->connect(out, c[i], c[0], 0, dis(rng)); |
| 346 | } |
| 347 | external.connect(out, c[1], 1, dis(rng)); |
| 348 | auto thr = [&out](shared c) { |
| 349 | TRACE(command, out) << "Thread " << c->id << " started." << std::endl; |
| 350 | weak ref = c; |
| 351 | for (;c->caller < c->count; ++c->caller) { |
| 352 | c->signal(std::move(c->caller)); |
| 353 | } |
| 354 | TRACE(command, out) << "Thread " << c->id << " resets shared." << std::endl; |
| 355 | c.reset(); |
| 356 | while((c = ref.lock())) { |
| 357 | ++c->caller; |
| 358 | c->signal(std::move(c->caller)); |
| 359 | c.reset(); |
| 360 | std::this_thread::sleep_for(delay*25); |
| 361 | } |
| 362 | }; |
| 363 | for (unsigned i = 0; i < c.size(); ++i) { |
| 364 | TRACE(command, out) << "start thread " << i << std::endl; |
| 365 | t[i] = std::thread{thr, c[i]}; |
| 366 | } |
| 367 | } |