2023-04-24 13:29:35 -07:00
|
|
|
// Copyright (C) 2023 Christian Mazakas
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
|
|
|
|
|
#define BOOST_ENABLE_ASSERT_HANDLER
|
|
|
|
|
|
|
|
|
|
#include "latch.hpp"
|
|
|
|
|
|
|
|
|
|
#include <boost/core/lightweight_test.hpp>
|
|
|
|
|
|
|
|
|
|
#include <thread>
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
struct exception
|
|
|
|
|
{
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace boost {
|
|
|
|
|
void assertion_failed(
|
|
|
|
|
char const* expr, char const* function, char const* file, long line)
|
|
|
|
|
{
|
|
|
|
|
(void)expr;
|
|
|
|
|
(void)function;
|
|
|
|
|
(void)file;
|
|
|
|
|
(void)line;
|
|
|
|
|
throw exception{};
|
|
|
|
|
}
|
|
|
|
|
} // namespace boost
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
void test_max() { BOOST_TEST_EQ(boost::latch::max(), INT_MAX); }
|
|
|
|
|
|
|
|
|
|
void test_constructor()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
auto const f = [] {
|
|
|
|
|
boost::latch l(-1);
|
|
|
|
|
(void)l;
|
|
|
|
|
};
|
|
|
|
|
BOOST_TEST_THROWS(f(), exception);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::ptrdiff_t n = 0;
|
|
|
|
|
|
|
|
|
|
boost::latch l(n);
|
|
|
|
|
BOOST_TEST(l.try_wait());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
std::ptrdiff_t n = 16;
|
|
|
|
|
|
|
|
|
|
boost::latch l(n);
|
|
|
|
|
BOOST_TEST_NOT(l.try_wait());
|
|
|
|
|
|
|
|
|
|
l.count_down(16);
|
|
|
|
|
BOOST_TEST(l.try_wait());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if PTRDIFF_MAX > INT_MAX
|
|
|
|
|
{
|
|
|
|
|
auto const f = [] {
|
|
|
|
|
std::ptrdiff_t n = INT_MAX;
|
|
|
|
|
n += 10;
|
|
|
|
|
boost::latch l(n);
|
|
|
|
|
(void)l;
|
|
|
|
|
};
|
|
|
|
|
BOOST_TEST_THROWS(f(), exception);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_count_down_and_wait()
|
|
|
|
|
{
|
|
|
|
|
constexpr std::ptrdiff_t n = 1024;
|
|
|
|
|
|
|
|
|
|
boost::latch l(2 * n);
|
|
|
|
|
|
|
|
|
|
bool bs[] = {false, false};
|
|
|
|
|
|
|
|
|
|
std::thread t1([&] {
|
|
|
|
|
l.wait();
|
|
|
|
|
BOOST_TEST(bs[0]);
|
|
|
|
|
BOOST_TEST(bs[1]);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
std::thread t2([&] {
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
if (i == (n - 1)) {
|
|
|
|
|
bs[0] = true;
|
|
|
|
|
} else {
|
|
|
|
|
BOOST_TEST_NOT(l.try_wait());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
l.count_down(1);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
if (i == (n - 1)) {
|
|
|
|
|
bs[1] = true;
|
|
|
|
|
} else {
|
|
|
|
|
BOOST_TEST_NOT(l.try_wait());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
l.count_down(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t1.join();
|
|
|
|
|
t2.join();
|
|
|
|
|
|
|
|
|
|
BOOST_TEST(l.try_wait());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void test_arrive_and_wait()
|
|
|
|
|
{
|
2023-04-25 13:41:36 -07:00
|
|
|
std::ptrdiff_t const n = 16;
|
2023-04-24 13:29:35 -07:00
|
|
|
|
|
|
|
|
boost::latch l(2 * n);
|
|
|
|
|
|
|
|
|
|
int xs[n] = {0};
|
|
|
|
|
|
|
|
|
|
std::vector<std::thread> threads;
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
2023-04-25 13:41:36 -07:00
|
|
|
threads.emplace_back([&l, &xs, i, n] {
|
|
|
|
|
(void)n;
|
2023-04-24 13:29:35 -07:00
|
|
|
for (int j = 0; j < n; ++j) {
|
|
|
|
|
BOOST_TEST_EQ(xs[j], 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
l.arrive_and_wait(2);
|
|
|
|
|
|
|
|
|
|
xs[i] = 1;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto& t : threads) {
|
|
|
|
|
t.join();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < n; ++i) {
|
|
|
|
|
BOOST_TEST_EQ(xs[i], 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
|
|
int main()
|
|
|
|
|
{
|
|
|
|
|
test_max();
|
|
|
|
|
test_constructor();
|
|
|
|
|
test_count_down_and_wait();
|
|
|
|
|
test_arrive_and_wait();
|
|
|
|
|
|
|
|
|
|
return boost::report_errors();
|
|
|
|
|
}
|