atomic/test/lightweight_test_stream.hpp
Andrey Semashev 76e25f36a3 Added generic implementation of C++20 waiting/notifying operations.
The generic implementation is based on the lock pool. A list of condition
variables (or waiting futexes) is added per lock. Basically, the lock
pool serves as a global hash table, where each lock represents
a bucket and each wait state is an element. Every wait operation
allocates a wait state keyed on the pointer to the atomic object. Notify
operations look up the wait state by the atomic pointer and notify
the condition variable/futex. The corresponding lock needs to be acquired
to protect the wait state list during all wait/notify operations.

Backends not involving the lock pool are going to be added later.

The implementation of wait operation extends the C++20 definition in that
it returns the newly loaded value instead of void. This allows the caller
to avoid loading the value himself.

The waiting/notifying operations are not address-free. Address-free variants
will be added later.

Added tests for the new operations and refactored existing tests for atomic
operations. Added docs for the new operations.
2020-06-03 01:39:20 +03:00

99 lines
2.9 KiB
C++

// Copyright (c) 2020 Andrey Semashev
//
// 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)
#ifndef BOOST_ATOMIC_TEST_LIGHTWEIGHT_TEST_STREAM_HPP_INCLUDED_
#define BOOST_ATOMIC_TEST_LIGHTWEIGHT_TEST_STREAM_HPP_INCLUDED_
#include <iostream>
#include <boost/config.hpp>
struct test_stream_type
{
typedef std::ios_base& (*ios_base_manip)(std::ios_base&);
typedef std::basic_ios< char, std::char_traits< char > >& (*basic_ios_manip)(std::basic_ios< char, std::char_traits< char > >&);
typedef std::ostream& (*stream_manip)(std::ostream&);
template< typename T >
test_stream_type const& operator<< (T const& value) const
{
std::cerr << value;
return *this;
}
test_stream_type const& operator<< (ios_base_manip manip) const
{
std::cerr << manip;
return *this;
}
test_stream_type const& operator<< (basic_ios_manip manip) const
{
std::cerr << manip;
return *this;
}
test_stream_type const& operator<< (stream_manip manip) const
{
std::cerr << manip;
return *this;
}
// Make sure characters are printed as numbers if tests fail
test_stream_type const& operator<< (char value) const
{
std::cerr << static_cast< int >(value);
return *this;
}
test_stream_type const& operator<< (signed char value) const
{
std::cerr << static_cast< int >(value);
return *this;
}
test_stream_type const& operator<< (unsigned char value) const
{
std::cerr << static_cast< unsigned int >(value);
return *this;
}
test_stream_type const& operator<< (short value) const
{
std::cerr << static_cast< int >(value);
return *this;
}
test_stream_type const& operator<< (unsigned short value) const
{
std::cerr << static_cast< unsigned int >(value);
return *this;
}
#if defined(BOOST_HAS_INT128)
// Some GCC versions don't provide output operators for __int128
test_stream_type const& operator<< (boost::int128_type const& v) const
{
std::cerr << static_cast< long long >(v);
return *this;
}
test_stream_type const& operator<< (boost::uint128_type const& v) const
{
std::cerr << static_cast< unsigned long long >(v);
return *this;
}
#endif // defined(BOOST_HAS_INT128)
#if defined(BOOST_HAS_FLOAT128)
// libstdc++ does not provide output operators for __float128
test_stream_type const& operator<< (boost::float128_type const& v) const
{
std::cerr << static_cast< double >(v);
return *this;
}
#endif // defined(BOOST_HAS_FLOAT128)
};
const test_stream_type test_stream = {};
#define BOOST_LIGHTWEIGHT_TEST_OSTREAM test_stream
#include <boost/core/lightweight_test.hpp>
#endif // BOOST_ATOMIC_TEST_LIGHTWEIGHT_TEST_STREAM_HPP_INCLUDED_