// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #pragma once #include namespace vespalib::test { /** * Generally useful rendezvous implementations. **/ struct ThreadMeets { // can be used as a simple thread barrier struct Nop : vespalib::Rendezvous { explicit Nop(size_t N) : vespalib::Rendezvous(N) {} void operator()() { rendezvous(false); } void mingle() override; }; // calculate the average value across threads struct Avg : Rendezvous { explicit Avg(size_t n) : Rendezvous(n) {} double operator()(double value) { return rendezvous(value); } void mingle() override; }; // threads vote for true/false, majority wins (false on tie) struct Vote : Rendezvous { explicit Vote(size_t n) : Rendezvous(n) {} bool operator()(bool flag) { return rendezvous(flag); } void mingle() override; }; // sum of values across all threads template struct Sum : vespalib::Rendezvous { using vespalib::Rendezvous::in; using vespalib::Rendezvous::out; using vespalib::Rendezvous::size; using vespalib::Rendezvous::rendezvous; explicit Sum(size_t N) : vespalib::Rendezvous(N) {} T operator()(T value) { return rendezvous(value); } void mingle() override { T acc = in(0); for (size_t i = 1; i < size(); ++i) { acc += in(i); } for (size_t i = 0; i < size(); ++i) { out(i) = acc; } } }; // maximum of values across all threads template struct Max : vespalib::Rendezvous { using vespalib::Rendezvous::in; using vespalib::Rendezvous::out; using vespalib::Rendezvous::size; using vespalib::Rendezvous::rendezvous; explicit Max(size_t N) : vespalib::Rendezvous(N) {} T operator()(T value) { return rendezvous(value); } void mingle() override { T max = in(0); for (size_t i = 1; i < size(); ++i) { if (in(i) > max) { max = in(i); } } for (size_t i = 0; i < size(); ++i) { out(i) = max; } } }; // minimum of values across all threads template struct Min : vespalib::Rendezvous { using vespalib::Rendezvous::in; using vespalib::Rendezvous::out; using vespalib::Rendezvous::size; using vespalib::Rendezvous::rendezvous; explicit Min(size_t N) : vespalib::Rendezvous(N) {} T operator()(T value) { return rendezvous(value); } void mingle() override { T min = in(0); for (size_t i = 1; i < size(); ++i) { if (in(i) < min) { min = in(i); } } for (size_t i = 0; i < size(); ++i) { out(i) = min; } } }; // range of values across all threads template struct Range : vespalib::Rendezvous { using vespalib::Rendezvous::in; using vespalib::Rendezvous::out; using vespalib::Rendezvous::size; using vespalib::Rendezvous::rendezvous; explicit Range(size_t N) : vespalib::Rendezvous(N) {} T operator()(T value) { return rendezvous(value); } void mingle() override { T min = in(0); T max = in(0); for (size_t i = 1; i < size(); ++i) { if (in(i) < min) { min = in(i); } if (in(i) > max) { max = in(i); } } T result = (max - min); for (size_t i = 0; i < size(); ++i) { out(i) = result; } } }; // swap values between 2 threads template struct Swap : vespalib::Rendezvous { using vespalib::Rendezvous::in; using vespalib::Rendezvous::out; using vespalib::Rendezvous::rendezvous; Swap() : vespalib::Rendezvous(2) {} T operator()(T input) { return rendezvous(input); } void mingle() override { out(1) = std::move(in(0)); out(0) = std::move(in(1)); } }; }; }