diff --git a/build/Jamfile.v2 b/build/Jamfile.v2 index b11fd865..e7444e07 100644 --- a/build/Jamfile.v2 +++ b/build/Jamfile.v2 @@ -33,6 +33,7 @@ lib boost_fiber context.cpp detail/spinlock.cpp fiber.cpp + future.cpp interruption.cpp mutex.cpp properties.cpp diff --git a/include/boost/fiber/exceptions.hpp b/include/boost/fiber/exceptions.hpp index c8990069..e9b51742 100644 --- a/include/boost/fiber/exceptions.hpp +++ b/include/boost/fiber/exceptions.hpp @@ -159,8 +159,39 @@ public: } }; -using std::future_errc; -using std::future_category; + +enum class future_errc { + broken_promise = 1, + future_already_retrieved = 2, + promise_already_satisfied = 3, + no_state = 4 +}; + +BOOST_FIBERS_DECL +std::error_category const& future_category() noexcept; + +}} + +namespace std { + +template<> +struct is_error_code_enum< boost::fibers::future_errc > : public true_type { +}; + +inline +std::error_code make_error_code( boost::fibers::future_errc e) noexcept { + return std::error_code( static_cast< int >( e), boost::fibers::future_category() ); +} + +inline +std::error_condition make_error_condition( boost::fibers::future_errc e) noexcept { + return std::error_condition( static_cast< int >( e), boost::fibers::future_category() ); +} + +} + +namespace boost { +namespace fibers { class future_error : public std::logic_error { private: diff --git a/src/future.cpp b/src/future.cpp index f251058b..0059b457 100644 --- a/src/future.cpp +++ b/src/future.cpp @@ -9,9 +9,64 @@ namespace boost { namespace fibers { +class future_error_category : public std::error_category { +public: + virtual const char* name() const noexcept { + return "fiber-future"; + } + + virtual std::error_condition default_error_condition( int ev) const noexcept { + switch ( static_cast< future_errc >( ev) ) { + case future_errc::broken_promise: + return std::error_condition( + static_cast< int >( future_errc::broken_promise), + future_category() ); + case future_errc::future_already_retrieved: + return std::error_condition( + static_cast< int >( future_errc::future_already_retrieved), + future_category() ); + case future_errc::promise_already_satisfied: + return std::error_condition( + static_cast< int >( future_errc::promise_already_satisfied), + future_category() ); + case future_errc::no_state: + return std::error_condition( + static_cast< + int >( future_errc::no_state), + future_category() ); + default: + return std::error_condition( + ev, + * this); + } + } + + virtual bool equivalent( std::error_code const& code, int condition) const noexcept { + return * this == code.category() && + static_cast< int >( default_error_condition( code.value() ).value() ) == condition; + } + + virtual std::string message( int ev) const { + switch ( static_cast< future_errc >( ev) ) { + case future_errc::broken_promise: + return std::string("The associated promise has been destructed prior " + "to the associated state becoming ready."); + case future_errc::future_already_retrieved: + return std::string("The future has already been retrieved from " + "the promise or packaged_task."); + case future_errc::promise_already_satisfied: + return std::string("The state of the promise has already been set."); + case future_errc::no_state: + return std::string("Operation not permitted on an object without " + "an associated state."); + } + return std::string("unspecified future_errc value\n"); + } +}; + BOOST_FIBERS_DECL std::error_category const& future_category() noexcept { - static std::future_error_category cat; + static fibers::future_error_category cat; return cat; }