Calls random member functions of ConcurrentQueue for a limited time. Ensures that total equals 0 when all jobs are complete/canceled by: setting each job's summand to 1; subtracting a job set's size from total before enqueuing jobs in the set; adding canceled job count to total after cancelation.
| 287 | //! * subtracting a job set's size from total before enqueuing jobs in the set; |
| 288 | //! * adding canceled job count to total after cancelation. |
| 289 | class RandomCaller |
| 290 | { |
| 291 | public: |
| 292 | explicit RandomCaller(ConcurrentQueue &queue, Total &total, int threadId, |
| 293 | int queueThreadCount, RandomEngine &engine, |
| 294 | bool boostEnqueueOperationWeight) |
| 295 | : queue(queue), |
| 296 | total(total), |
| 297 | threadId { threadId }, |
| 298 | boostEnqueueOperationWeight { boostEnqueueOperationWeight }, |
| 299 | printer(total, threadId, queueThreadCount), |
| 300 | engine(engine) |
| 301 | { |
| 302 | } |
| 303 | |
| 304 | void operator()() |
| 305 | { |
| 306 | constexpr auto testDuration = chrono::milliseconds(10); |
| 307 | const auto testStartTime = Clock::now(); |
| 308 | |
| 309 | auto operation = operationDistribution(); |
| 310 | do { |
| 311 | switch (operation(engine)) { |
| 312 | case 0: |
| 313 | enqueue(); |
| 314 | break; |
| 315 | case 1: |
| 316 | cancel(); |
| 317 | break; |
| 318 | case 2: |
| 319 | waitAndPrint(queue, printer); |
| 320 | break; |
| 321 | default: |
| 322 | qFatal("Unsupported operation."); |
| 323 | } |
| 324 | } while (Clock::now() - testStartTime < testDuration); |
| 325 | } |
| 326 | |
| 327 | private: |
| 328 | int randomInt(int a, int b) |
| 329 | { |
| 330 | return uniformInt(engine, decltype(uniformInt)::param_type(a, b)); |
| 331 | } |
| 332 | |
| 333 | using OperationDistribution = std::discrete_distribution<int>; |
| 334 | |
| 335 | void printProbabilities(const OperationDistribution &distribution) const |
| 336 | { |
| 337 | auto p = distribution.probabilities(); |
| 338 | constexpr std::size_t expectedProbabilityCount { 3 }; |
| 339 | if (p.size() != expectedProbabilityCount) |
| 340 | qFatal("Wrong number of operation probabilities: %zu != %zu", p.size(), expectedProbabilityCount); |
| 341 | |
| 342 | for (auto &x : p) |
| 343 | x *= 100; // Convert to percentages. |
| 344 | log() << QStringLiteral("#%1 operation probabilities: e=%2%, c=%3%, w=%4%.").arg(threadId).arg(p[0]).arg(p[1]).arg(p[2]); |
| 345 | } |
| 346 |