2
0
mirror of https://github.com/boostorg/leaf.git synced 2026-02-09 23:22:29 +00:00
Files
leaf/test/tl_slot_test.cpp
Emil Dotchevski 53daeb8ac3 initial commit
2018-09-16 15:56:34 -07:00

241 lines
5.5 KiB
C++

//Copyright (c) 2018 Emil Dotchevski
//Copyright (c) 2018 Second Spectrum, Inc.
//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)
#include <boost/leaf/detail/tl_slot.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <future>
#include <vector>
#include <algorithm>
namespace leaf = boost::leaf;
struct error { };
template <class T>
int &
count()
{
static thread_local int c=0;
return c;
}
template <class Tag>
class
my_info
{
my_info & operator=( my_info const & ) = delete;
public:
int value;
explicit
my_info( int value ):
value(value)
{
BOOST_TEST(++count<my_info>()>0);
}
my_info( my_info const & x ):
value(x.value)
{
BOOST_TEST(++count<my_info>()>0);
}
my_info( my_info && x ):
value(x.value)
{
x.value=-1;
BOOST_TEST(++count<my_info>()>0);
}
~my_info()
{
BOOST_TEST(--count<my_info>()>=0);
}
};
class
throws_on_copy
{
throws_on_copy & operator=( throws_on_copy const & )=delete;
public:
int value;
throws_on_copy()
{
BOOST_TEST(++count<throws_on_copy>()>0);
}
throws_on_copy( throws_on_copy const & )
{
throw error();
}
throws_on_copy( throws_on_copy && )
{
BOOST_TEST(++count<throws_on_copy>()>0);
}
~throws_on_copy()
{
BOOST_TEST(--count<throws_on_copy>()>=0);
}
};
struct A;
struct B;
struct C;
void
run_tests()
{
using leaf::leaf_detail::tl_slot;
auto & tls = leaf::leaf_detail::tl_slot_state::tl_instance();
{
{
throws_on_copy a;
BOOST_TEST(count<throws_on_copy>()==1);
auto & x = tl_slot<throws_on_copy>::tl_instance();
BOOST_TEST(!x.is_open());
BOOST_TEST(!x.put(a));
BOOST_TEST(count<throws_on_copy>()==1);
BOOST_TEST(!x.has_value());
BOOST_TEST(x.open()==1);
BOOST_TEST(x.put(throws_on_copy()));
BOOST_TEST(count<throws_on_copy>()==2);
BOOST_TEST(x.has_value());
try
{
(void) x.put(a);
BOOST_TEST(false);
}
catch( error & )
{
}
BOOST_TEST(count<throws_on_copy>()==1);
BOOST_TEST(!x.has_value());
BOOST_TEST(x.is_open());
BOOST_TEST(x.close()==0);
}
BOOST_TEST(count<throws_on_copy>()==0);
{
auto & x = tl_slot<my_info<A>>::tl_instance();
BOOST_TEST(&x==&tl_slot<my_info<A>>::tl_instance());
BOOST_TEST(!x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(!x.put(my_info<A>(42)));
BOOST_TEST(!x.has_value());
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.open()==2);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<A>>()==0);
BOOST_TEST(x.put(my_info<A>(42)));
BOOST_TEST(x.close()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(x.has_value());
BOOST_TEST(count<my_info<A>>()==1);
BOOST_TEST(x.close()==0);
BOOST_TEST(!x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<A>>()==0);
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<A>>()==0);
BOOST_TEST(x.put(my_info<A>(43)));
BOOST_TEST(x.is_open());
BOOST_TEST(x.has_value());
BOOST_TEST(x.open()==2);
BOOST_TEST(x.is_open());
BOOST_TEST(x.close()==1);
BOOST_TEST(x.close()==0);
BOOST_TEST(!x.has_value());
}
{
auto & x = tl_slot<my_info<B>>::tl_instance();
BOOST_TEST(&x==&tl_slot<my_info<B>>::tl_instance());
BOOST_TEST(!x.is_open());
BOOST_TEST(!x.has_value());
{
my_info<B> tmp(42);
BOOST_TEST(!x.put(tmp));
}
BOOST_TEST(!x.has_value());
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.open()==2);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<B>>()==0);
{
my_info<B> tmp(42);
BOOST_TEST(x.put(tmp));
}
BOOST_TEST(x.close()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(x.has_value());
BOOST_TEST(count<my_info<B>>()==1);
BOOST_TEST(x.close()==0);
BOOST_TEST(!x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<B>>()==0);
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(count<my_info<B>>()==0);
{
my_info<B> tmp(43);
BOOST_TEST(x.put(tmp));
}
BOOST_TEST(x.is_open());
BOOST_TEST(x.has_value());
BOOST_TEST(x.open()==2);
BOOST_TEST(x.is_open());
BOOST_TEST(x.close()==1);
BOOST_TEST(x.close()==0);
BOOST_TEST(!x.has_value());
}
{
auto & x = tl_slot<my_info<C>>::tl_instance();
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.put(my_info<C>(42)));
BOOST_TEST(x.has_value());
x.reset();
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.close()==0);
}
{
auto & x = tl_slot<my_info<A>>::tl_instance();
BOOST_TEST(x.open()==1);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.put(my_info<A>(42)));
BOOST_TEST(x.has_value());
my_info<A> inf = x.extract_value();
BOOST_TEST(inf.value==42);
BOOST_TEST(x.is_open());
BOOST_TEST(!x.has_value());
BOOST_TEST(x.close()==0);
}
}
BOOST_TEST(count<my_info<A>>()==0);
BOOST_TEST(count<my_info<B>>()==0);
BOOST_TEST(count<my_info<C>>()==0);
}
int
main()
{
std::vector<std::future<void>> fut;
std::generate_n( std::inserter(fut,fut.end()), 1, [ ]
{
return std::async( std::launch::async, &run_tests );
} );
for( auto & i : fut )
i.wait();
for( auto & i : fut )
i.get();
return boost::report_errors();
}