Overview
Boost.Compat is a repository of C++11 implementations of standard components added in later C++ standards. Its target audience is Boost library authors whose libraries support a lower C++ standard, but wish to utilize a component added in a subsequent one.
The criteria for inclusion in Boost.Compat are as follows:
-
The implementation should be relatively simple and header-only.
-
The component must implement the standard functionality exactly, without deviations or extensions. This allows (but does not require) the implementation to be a simple
using
declaration in case the standard component is available. -
The component must not depend on any Boost libraries except Boost.Config, Boost.Assert, or Boost.ThrowException.
-
The component must not be a vocabulary type, visible in the library APIs. The user should never see a
boost::compat
type; the use of Compat types should be confined to library implementations.
Revision History
Changes in 1.83.0
-
Added
latch.hpp
, an implementation ofstd::latch
(contributed by Christian Mazakas.) -
Added
shared_lock.hpp
, a (partial) implementation ofstd::shared_lock
(contributed by Christian Mazakas.)
<boost/compat/latch.hpp>
Description
The header <boost/compat/latch.hpp>
implements, in a portable way, the C++20
<latch>
header.
latch
is a single-use barrier which counts downwards, enabling synchronization
between a set of threads. The counter can be manually decremented by any value,
but decrementing below zero causes undefined behavior. The maximum number of waiters is
specified to be boost::compat::latch::max()
.
Example
std::ptrdiff_t const num_threads = 16;
boost::compat::latch l(num_threads);
std::vector<std::thread> threads;
for (int i = 0; i < num_threads; ++i) {
threads.emplace_back([&l] {
// do some preliminary work here...
// block until all threads have reached this statement
l.arrive_and_wait();
// continue with further work...
});
}
for (auto& t: threads) { t.join(); }
Synopsis
namespace boost
{
namespace compat
{
class latch {
explicit latch(std::ptrdiff_t expected);
latch(latch const &) = delete;
latch &operator=(latch const &) = delete;
~latch() = default;
void count_down(std::ptrdiff_t n = 1);
bool try_wait() const noexcept;
void wait() const;
void arrive_and_wait(std::ptrdiff_t n = 1);
static constexpr std::ptrdiff_t max() noexcept;
};
} // namespace compat
} // namespace boost
Constructors
Counter Constructor
explicit latch(std::ptrdiff_t expected);
Preconditions: |
|
Effects: |
Constructs a latch with an internal counter value of |
Copy Constructor
latch(latch const &) = delete;
latch
is not copyable or movable.
Member Functions
count_down
void count_down(std::ptrdiff_t n = 1);
Preconditions: |
|
Effects: |
Decrements the internal counter by |
try_wait
bool try_wait() const noexcept;
Returns a boolean indicating whether or not the latch’s internal counter has reached 0 (true
) or not (false
).
wait
void wait() const;
Blocks the current thread until the internal counter has reached 0.
arrive_and_wait
void arrive_and_wait(std::ptrdiff_t n = 1);
Preconditions: |
|
Effects: |
Decrements the internal counter by |
max
static constexpr std::ptrdiff_t max() noexcept;
Returns an implementation-defined number representing the maximum amount of waiters. Currently PTRDIFF_MAX.
<boost/compat/shared_lock.hpp>
Description
The header <boost/compat/shared_lock.hpp>
implements, in a portable way, the C++14
std::shared_lock
class template.
The class shared_lock
is a RAII wrapper that manages locking and unlocking
the provided Mutex, provided that it implements SharedLockable.
This is the shared analog of unique_lock
and calls lock_shared()
instead of lock()
.
Example
#include <boost/compat/shared_lock.hpp>
shared_mutex m;
// acquire the lock by calling `m.lock_shared()`
// `m.unlock_shared()` is called automatically for us by `guard` now
boost::compat::shared_lock<shared_mutex> guard(m);
assert(guard.owns_lock());
Synopsis
namespace boost {
namespace compat {
template <class Mutex>
class shared_lock;
template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
template <class Mutex>
class shared_lock {
using mutex_type = Mutex;
shared_lock() noexcept = default;
explicit shared_lock( mutex_type& m );
shared_lock( mutex_type& m, std::defer_lock_t ) noexcept;
shared_lock( mutex_type& m, std::try_lock_t );
shared_lock( mutex_type& m, std::adopt_lock_t );
~shared_lock();
shared_lock( const shared_lock& ) = delete;
shared_lock& operator=( const shared_lock& ) = delete;
shared_lock( shared_lock&& u ) noexcept;
shared_lock& operator=( shared_lock&& u ) noexcept;
void lock();
bool try_lock();
void unlock();
void swap( shared_lock& u ) noexcept;
mutex_type* release() noexcept;
mutex_type* mutex() const noexcept;
bool owns_lock() const noexcept;
explicit operator bool() const noexcept;
};
} // namespace compat
} // namespace boost
Constructors
Default Constructor
shared_lock() noexcept = default;
Postconditions: |
|
Locking Constructor
explicit shared_lock( mutex_type& m );
Effects: |
Calls |
Postconditions: |
|
Deferred Constructor
shared_lock( mutex_type& m, std::defer_lock_t ) noexcept;
Postconditions: |
|
Try-to-Lock Constructor
shared_lock( mutex_type& m, std::try_lock_t );
Effects: |
Calls |
Postconditions: |
|
Adopting Constructor
shared_lock( mutex_type& m, std::adopt_lock_t );
Preconditions: |
|
PostConditions: |
|
Copy Constructor
shared_lock( const shared_lock& ) = delete;
shared_lock
is not copyable.
Move Constructor
shared_lock( shared_lock&& u ) noexcept;
Postconditions: |
|
Assignment
Copy Assignment
shared_lock& operator=( const shared_lock& ) = delete;
shared_lock
is not copyable.
Move Assignment
shared_lock& operator=( shared_lock&& u ) noexcept;
Effects: |
If |
Postconditions: |
|
Destructor
~shared_lock();
Effects: |
If |
Member Functions
Locking
lock
void lock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
Any exception caused by |
try_lock
bool try_lock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
Any exception caused by |
unlock
void unlock();
Effects: |
Calls |
Postconditions: |
|
Throws: |
|
Modifiers
swap
void swap( shared_lock& u ) noexcept;
Effects: |
Swaps the data members of |
release
mutex_type* release() noexcept;
Postconditions: |
|
Returns: |
The previous value of |
Free Function swap
template <class Mutex>
void swap( shared_lock<Mutex>& x, shared_lock<Mutex>& y ) noexcept;
Effects: |
Swaps the data members of |
Observers
mutex
mutex_type* mutex() const noexcept;
Returns: |
The value of the internal pointer, either |
owns_lock
bool owns_lock() const noexcept;
Returns: |
A boolean indicating whether or not the mutex is locked by the current
|
boolean conversion
explicit operator bool() const noexcept;
Returns: |
A boolean indicating whether or not the mutex is locked by the current
|
Copyright and License
This documentation is copyright 2023 Peter Dimov and contributors and is distributed under the Boost Software License, Version 1.0.