cppcoro/include/cppcoro/cancellation_registration.hpp
Lewis Baker 29ce3d2727 Avoid use of CALLBACK as template parameter name.
Windows.h defines CALLBACK as a macro which causes compile-errors
if included before the cancellation_registration.hpp header.
2017-06-11 20:17:52 +09:30

86 lines
2.9 KiB
C++

///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCORO_CANCELLATION_REGISTRATION_HPP_INCLUDED
#define CPPCORO_CANCELLATION_REGISTRATION_HPP_INCLUDED
#include <functional>
#include <utility>
#include <type_traits>
#include <atomic>
namespace cppcoro
{
class cancellation_token;
namespace detail
{
class cancellation_state;
struct cancellation_registration_list_chunk;
struct cancellation_registration_state;
}
class cancellation_registration
{
public:
/// Registers the callback to be executed when cancellation is requested
/// on the cancellation_token.
///
/// The callback will be executed if cancellation is requested for the
/// specified cancellation token. If cancellation has already been requested
/// then the callback will be executed immediately, before the constructor
/// returns. If cancellation has not yet been requested then the callback
/// will be executed on the first thread to request cancellation inside
/// the call to cancellation_source::request_cancellation().
///
/// \param token
/// The cancellation token to register the callback with.
///
/// \param callback
/// The callback to be executed when cancellation is requested on the
/// the cancellation_token. Note that callback must not throw an exception
/// if called when cancellation is requested otherwise std::terminate()
/// will be called.
///
/// \throw std::bad_alloc
/// If registration failed due to insufficient memory available.
template<
typename FUNC,
typename = std::enable_if_t<std::is_constructible_v<std::function<void()>, FUNC&&>>>
cancellation_registration(cancellation_token token, FUNC&& callback)
: m_callback(std::forward<FUNC>(callback))
{
register_callback(std::move(token));
}
cancellation_registration(const cancellation_registration& other) = delete;
cancellation_registration& operator=(const cancellation_registration& other) = delete;
/// Deregisters the callback.
///
/// After the destructor returns it is guaranteed that the callback
/// will not be subsequently called during a call to request_cancellation()
/// on the cancellation_source.
///
/// This may block if cancellation has been requested on another thread
/// is it will need to wait until this callback has finished executing
/// before the callback can be destroyed.
~cancellation_registration();
private:
friend class detail::cancellation_state;
friend struct detail::cancellation_registration_state;
void register_callback(cancellation_token&& token);
detail::cancellation_state* m_state;
std::function<void()> m_callback;
detail::cancellation_registration_list_chunk* m_chunk;
std::uint32_t m_entryIndex;
};
}
#endif