diff --git a/build/Jamfile.v2 b/build/Jamfile.v2
index f17f570..68f6ef4 100644
--- a/build/Jamfile.v2
+++ b/build/Jamfile.v2
@@ -45,6 +45,7 @@ explicit allocator_sources ;
lib boost_coroutine
: allocator_sources
detail/coroutine_context.cpp
+ exceptions.cpp
: shared:../../context/build//boost_context
;
diff --git a/example/cpp03/echo.cpp b/example/cpp03/echo.cpp
index e2b19f6..1219707 100644
--- a/example/cpp03/echo.cpp
+++ b/example/cpp03/echo.cpp
@@ -14,31 +14,31 @@
typedef boost::coroutines::coroutine< void >::pull_type pull_coro_t;
typedef boost::coroutines::coroutine< void >::push_type push_coro_t;
-void echo( pull_coro_t & c, int i)
+void echo( pull_coro_t & source, int i)
{
std::cout << i;
- c();
+ source();
}
-void runit( push_coro_t & ca)
+void runit( push_coro_t & sink1)
{
std::cout << "started! ";
for ( int i = 0; i < 10; ++i)
{
- push_coro_t c( boost::bind( echo, _1, i) );
- while ( c)
- c();
- ca();
+ push_coro_t sink2( boost::bind( echo, _1, i) );
+ while ( sink2)
+ sink2();
+ sink1();
}
}
int main( int argc, char * argv[])
{
{
- pull_coro_t c( runit);
- while ( c) {
+ pull_coro_t source( runit);
+ while ( source) {
std::cout << "-";
- c();
+ source();
}
}
diff --git a/example/cpp03/fibonacci.cpp b/example/cpp03/fibonacci.cpp
index 9154a6c..5f6dd4f 100644
--- a/example/cpp03/fibonacci.cpp
+++ b/example/cpp03/fibonacci.cpp
@@ -11,26 +11,26 @@
#include
#ifdef BOOST_COROUTINES_UNIDIRECT
-void fibonacci( boost::coroutines::coroutine< int >::push_type & c)
+void fibonacci( boost::coroutines::coroutine< int >::push_type & sink)
{
int first = 1, second = 1;
- c( first);
- c( second);
+ sink( first);
+ sink( second);
while ( true)
{
int third = first + second;
first = second;
second = third;
- c( third);
+ sink( third);
}
}
int main()
{
- boost::coroutines::coroutine< int >::pull_type c( fibonacci);
+ boost::coroutines::coroutine< int >::pull_type source( fibonacci);
boost::range_iterator<
boost::coroutines::coroutine< int >::pull_type
- >::type it( boost::begin( c) );
+ >::type it( boost::begin( source) );
for ( int i = 0; i < 10; ++i)
{
std::cout << * it << " ";
diff --git a/example/cpp03/parallel.cpp b/example/cpp03/parallel.cpp
index 7c952f7..29098e2 100644
--- a/example/cpp03/parallel.cpp
+++ b/example/cpp03/parallel.cpp
@@ -11,22 +11,22 @@
#include
#ifdef BOOST_COROUTINES_UNIDIRECT
-void first( boost::coroutines::coroutine< void >::push_type & c)
+void first( boost::coroutines::coroutine< void >::push_type & sink)
{
std::cout << "started first! ";
for ( int i = 0; i < 10; ++i)
{
- c();
+ sink();
std::cout << "a" << i;
}
}
-void second( boost::coroutines::coroutine< void >::push_type & c)
+void second( boost::coroutines::coroutine< void >::push_type & sink)
{
std::cout << "started second! ";
for ( int i = 0; i < 10; ++i)
{
- c();
+ sink();
std::cout << "b" << i;
}
}
@@ -34,12 +34,12 @@ void second( boost::coroutines::coroutine< void >::push_type & c)
int main( int argc, char * argv[])
{
{
- boost::coroutines::coroutine< void >::pull_type c1( boost::bind( first, _1) );
- boost::coroutines::coroutine< void >::pull_type c2( boost::bind( second, _1) );
- while ( c1 && c2) {
- c1();
+ boost::coroutines::coroutine< void >::pull_type source1( boost::bind( first, _1) );
+ boost::coroutines::coroutine< void >::pull_type source2( boost::bind( second, _1) );
+ while ( source1 && source2) {
+ source1();
std::cout << " ";
- c2();
+ source2();
std::cout << " ";
}
}
diff --git a/example/cpp03/power.cpp b/example/cpp03/power.cpp
index 370da0f..3a43b6a 100644
--- a/example/cpp03/power.cpp
+++ b/example/cpp03/power.cpp
@@ -13,14 +13,14 @@
#include
#ifdef BOOST_COROUTINES_UNIDIRECT
-void power( boost::coroutines::coroutine< int >::push_type & c, int number, int exponent)
+void power( boost::coroutines::coroutine< int >::push_type & sink, int number, int exponent)
{
int counter = 0;
int result = 1;
while ( counter++ < exponent)
{
result = result * number;
- c( result);
+ sink( result);
}
}
@@ -28,17 +28,17 @@ int main()
{
{
std::cout << "using range functions" << std::endl;
- boost::coroutines::coroutine< int >::pull_type c( boost::bind( power, _1, 2, 8) );
- boost::coroutines::coroutine< int >::pull_type::iterator e( boost::end( c) );
- for ( boost::coroutines::coroutine< int >::pull_type::iterator i( boost::begin( c) );
+ boost::coroutines::coroutine< int >::pull_type source( boost::bind( power, _1, 2, 8) );
+ boost::coroutines::coroutine< int >::pull_type::iterator e( boost::end( source) );
+ for ( boost::coroutines::coroutine< int >::pull_type::iterator i( boost::begin( source) );
i != e; ++i)
std::cout << * i << " ";
}
{
std::cout << "\nusing BOOST_FOREACH" << std::endl;
- boost::coroutines::coroutine< int >::pull_type c( boost::bind( power, _1, 2, 8) );
- BOOST_FOREACH( int i, c)
+ boost::coroutines::coroutine< int >::pull_type source( boost::bind( power, _1, 2, 8) );
+ BOOST_FOREACH( int i, source)
{ std::cout << i << " "; }
}
diff --git a/example/cpp03/segmented_stack.cpp b/example/cpp03/segmented_stack.cpp
index 814a5a0..6ca4b9f 100644
--- a/example/cpp03/segmented_stack.cpp
+++ b/example/cpp03/segmented_stack.cpp
@@ -32,17 +32,17 @@ void bar( int i)
}
#ifdef BOOST_COROUTINES_UNIDIRECT
-void foo( boost::coroutines::coroutine< void >::pull_type & c)
+void foo( boost::coroutines::coroutine< void >::pull_type & source)
{
bar( count);
- c();
+ source();
}
void thread_fn()
{
{
- boost::coroutines::coroutine< void >::push_type c( foo);
- c();
+ boost::coroutines::coroutine< void >::push_type sink( foo);
+ sink();
}
}
#else
diff --git a/example/cpp03/unwind.cpp b/example/cpp03/unwind.cpp
index 91b7e6c..bda050d 100644
--- a/example/cpp03/unwind.cpp
+++ b/example/cpp03/unwind.cpp
@@ -17,24 +17,24 @@ struct X : private boost::noncopyable
~X() { std::cout << "~X()" << std::endl; }
};
-void fn( boost::coroutines::coroutine< void >::push_type & c)
+void fn( boost::coroutines::coroutine< void >::push_type & sink)
{
X x;
int i = 0;
while ( true)
{
std::cout << "fn() : " << ++i << std::endl;
- c();
+ sink();
}
}
int main( int argc, char * argv[])
{
{
- boost::coroutines::coroutine< void >::pull_type c( fn);
+ boost::coroutines::coroutine< void >::pull_type source( fn);
for ( int k = 0; k < 3; ++k)
{
- c();
+ source();
}
std::cout << "destroying coroutine and unwinding stack" << std::endl;
}
diff --git a/example/cpp11/fibonacci.cpp b/example/cpp11/fibonacci.cpp
index c6545d7..fc1f1b9 100644
--- a/example/cpp11/fibonacci.cpp
+++ b/example/cpp11/fibonacci.cpp
@@ -12,21 +12,21 @@
#ifdef BOOST_COROUTINES_UNIDIRECT
int main()
{
- boost::coroutines::coroutine< int >::pull_type c(
- [&]( boost::coroutines::coroutine< int >::push_type & c) {
+ boost::coroutines::coroutine< int >::pull_type source(
+ [&]( boost::coroutines::coroutine< int >::push_type & sink) {
int first = 1, second = 1;
- c( first);
- c( second);
+ sink( first);
+ sink( second);
for ( int i = 0; i < 8; ++i)
{
int third = first + second;
first = second;
second = third;
- c( third);
+ sink( third);
}
});
- for ( auto i : c)
+ for ( auto i : source)
std::cout << i << " ";
std::cout << "\nDone" << std::endl;
diff --git a/include/boost/coroutine/all.hpp b/include/boost/coroutine/all.hpp
index d80ca20..e32a420 100644
--- a/include/boost/coroutine/all.hpp
+++ b/include/boost/coroutine/all.hpp
@@ -9,6 +9,7 @@
#include
#include
+#include
#include
#include
diff --git a/include/boost/coroutine/exceptions.hpp b/include/boost/coroutine/exceptions.hpp
new file mode 100644
index 0000000..f263429
--- /dev/null
+++ b/include/boost/coroutine/exceptions.hpp
@@ -0,0 +1,105 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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_COROUTINES_EXCEPTIONS_H
+#define BOOST_COROUTINES_EXCEPTIONS_H
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_PREFIX
+#endif
+
+namespace boost {
+namespace coroutines {
+namespace detail {
+
+struct forced_unwind {};
+
+}
+
+BOOST_SCOPED_ENUM_DECLARE_BEGIN(coroutine_errc)
+{
+ no_data = 1
+}
+BOOST_SCOPED_ENUM_DECLARE_END(coroutine_errc)
+
+BOOST_COROUTINES_DECL system::error_category const& coroutine_category() BOOST_NOEXCEPT;
+
+}
+
+namespace system {
+
+template<>
+struct is_error_code_enum< coroutines::coroutine_errc > : public true_type
+{};
+
+#ifdef BOOST_NO_CXX11_SCOPED_ENUMS
+template<>
+struct is_error_code_enum< coroutines::coroutine_errc::enum_type > : public true_type
+{};
+#endif
+
+inline
+error_code make_error_code( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
+{
+ return error_code( underlying_cast< int >( e), coroutines::coroutine_category() );
+}
+
+inline
+error_condition make_error_condition( coroutines::coroutine_errc e) //BOOST_NOEXCEPT
+{
+ return error_condition( underlying_cast< int >( e), coroutines::coroutine_category() );
+}
+
+}
+
+namespace coroutines {
+
+class coroutine_error : public std::logic_error
+{
+private:
+ system::error_code ec_;
+
+public:
+ coroutine_error( system::error_code ec) :
+ logic_error( ec.message() ),
+ ec_( ec)
+ {}
+
+ system::error_code const& code() const BOOST_NOEXCEPT
+ { return ec_; }
+
+ const char* what() const throw()
+ { return code().message().c_str(); }
+};
+
+class invalid_result : public coroutine_error
+{
+public:
+ invalid_result() :
+ coroutine_error(
+ system::make_error_code(
+ coroutine_errc::no_data) )
+ {}
+};
+
+}}
+
+#ifdef BOOST_HAS_ABI_HEADERS
+# include BOOST_ABI_SUFFIX
+#endif
+
+#endif // BOOST_COROUTINES_EXCEPTIONS_H
diff --git a/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp b/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp
index 020f97c..a932edd 100644
--- a/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp
+++ b/include/boost/coroutine/v1/detail/coroutine_base_resume.hpp
@@ -22,7 +22,7 @@
#include
#include
-#include
+#include
#include
#include
diff --git a/include/boost/coroutine/v1/detail/coroutine_object.hpp b/include/boost/coroutine/v1/detail/coroutine_object.hpp
index f6348c2..2f260a3 100644
--- a/include/boost/coroutine/v1/detail/coroutine_object.hpp
+++ b/include/boost/coroutine/v1/detail/coroutine_object.hpp
@@ -21,7 +21,7 @@
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/include/boost/coroutine/v2/coroutine.hpp b/include/boost/coroutine/v2/coroutine.hpp
index ed26c2e..f166a19 100644
--- a/include/boost/coroutine/v2/coroutine.hpp
+++ b/include/boost/coroutine/v2/coroutine.hpp
@@ -16,6 +16,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -26,6 +27,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -1079,7 +1081,7 @@ public:
R get() const
{
- BOOST_ASSERT( has_result() );
+ BOOST_ASSERT( ! empty() );
return impl_->get();
}
@@ -1156,17 +1158,27 @@ public:
}
reference_t operator*() const
- { return const_cast< optional< R > & >( val_).get(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R > & >( val_).get();
+ }
pointer_t operator->() const
- { return const_cast< optional< R > & >( val_).get_ptr(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R > & >( val_).get_ptr();
+ }
};
class const_iterator : public std::iterator< std::input_iterator_tag, const typename remove_reference< R >::type >
{
private:
pull_coroutine< R > * c_;
- optional< R > val_;
+ optional< R > val_;
void fetch_()
{
@@ -1234,10 +1246,20 @@ public:
}
reference_t operator*() const
- { return val_.get(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get();
+ }
pointer_t operator->() const
- { return val_.get_ptr(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get_ptr();
+ }
};
};
@@ -1579,11 +1601,7 @@ public:
}
R & get() const
- {
- BOOST_ASSERT( has_result() );
-
- return impl_->get();
- }
+ { return impl_->get(); }
class iterator : public std::iterator< std::input_iterator_tag, R >
{
@@ -1657,10 +1675,20 @@ public:
}
reference_t operator*() const
- { return const_cast< optional< R & > & >( val_).get(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R & > & >( val_).get();
+ }
pointer_t operator->() const
- { return const_cast< optional< R & > & >( val_).get_ptr(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return const_cast< optional< R & > & >( val_).get_ptr();
+ }
};
class const_iterator : public std::iterator< std::input_iterator_tag, R >
@@ -1735,10 +1763,20 @@ public:
}
reference_t operator*() const
- { return val_.get(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get();
+ }
pointer_t operator->() const
- { return val_.get_ptr(); }
+ {
+ if ( ! val_)
+ boost::throw_exception(
+ invalid_result() );
+ return val_.get_ptr();
+ }
};
};
diff --git a/include/boost/coroutine/v2/detail/pull_coroutine_base.hpp b/include/boost/coroutine/v2/detail/pull_coroutine_base.hpp
index b5d049d..74cdc4d 100644
--- a/include/boost/coroutine/v2/detail/pull_coroutine_base.hpp
+++ b/include/boost/coroutine/v2/detail/pull_coroutine_base.hpp
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
#include
#include
@@ -21,7 +22,7 @@
#include
#include
#include
-#include
+#include
#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
@@ -130,8 +131,9 @@ public:
R get() const
{
- BOOST_ASSERT( has_result() );
-
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
return result_.get();
}
};
@@ -232,8 +234,9 @@ public:
R & get() const
{
- BOOST_ASSERT( has_result() );
-
+ if ( ! has_result() )
+ boost::throw_exception(
+ invalid_result() );
return * result_.get();
}
};
diff --git a/include/boost/coroutine/v2/detail/pull_coroutine_object.hpp b/include/boost/coroutine/v2/detail/pull_coroutine_object.hpp
index 08d0b76..30affdc 100644
--- a/include/boost/coroutine/v2/detail/pull_coroutine_object.hpp
+++ b/include/boost/coroutine/v2/detail/pull_coroutine_object.hpp
@@ -21,7 +21,7 @@
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/include/boost/coroutine/v2/detail/push_coroutine_base.hpp b/include/boost/coroutine/v2/detail/push_coroutine_base.hpp
index 595a167..511da61 100644
--- a/include/boost/coroutine/v2/detail/push_coroutine_base.hpp
+++ b/include/boost/coroutine/v2/detail/push_coroutine_base.hpp
@@ -17,7 +17,7 @@
#include
#include
-#include
+#include
#include
#ifdef BOOST_HAS_ABI_HEADERS
diff --git a/include/boost/coroutine/v2/detail/push_coroutine_object.hpp b/include/boost/coroutine/v2/detail/push_coroutine_object.hpp
index 52a7569..0f840f2 100644
--- a/include/boost/coroutine/v2/detail/push_coroutine_object.hpp
+++ b/include/boost/coroutine/v2/detail/push_coroutine_object.hpp
@@ -21,7 +21,7 @@
#include
#include
-#include
+#include
#include
#include
#include
diff --git a/src/exceptions.cpp b/src/exceptions.cpp
new file mode 100644
index 0000000..3b7761a
--- /dev/null
+++ b/src/exceptions.cpp
@@ -0,0 +1,36 @@
+
+// Copyright Oliver Kowalke 2009.
+// 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
+
+namespace boost {
+namespace coroutines {
+
+class coroutine_error_category : public system::error_category
+{
+public:
+ virtual const char* name() const BOOST_NOEXCEPT
+ { return "coroutine"; }
+
+ virtual std::string message( int ev) const
+ {
+ switch (BOOST_SCOPED_ENUM_NATIVE(coroutine_errc)(ev))
+ {
+ case coroutine_errc::no_data:
+ return std::string("Operation not permitted because coroutine "
+ "has no valid result.");
+ }
+ return std::string("unspecified coroutine_errc value\n");
+ }
+};
+
+system::error_category const& coroutine_category() BOOST_NOEXCEPT
+{
+ static coroutines::coroutine_error_category cat;
+ return cat;
+}
+
+}}
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index 555c8ce..2c0b497 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -18,6 +18,7 @@ project boost/coroutine/test
../../test/build//boost_unit_test_framework
/boost/context//boost_context
/boost/coroutine//boost_coroutine
+ /boost/system//boost_system
gcc-4.7,on:-fsplit-stack
gcc-4.8,on:-fsplit-stack
static
diff --git a/test/test_coroutine.cpp b/test/test_coroutine.cpp
index 1a82e86..c915866 100644
--- a/test/test_coroutine.cpp
+++ b/test/test_coroutine.cpp
@@ -197,6 +197,9 @@ void f19( coro::coroutine< const int* >::push_type & c, std::vector< const int *
{ c( ptr); }
}
+void f20( coro::coroutine< int >::push_type &)
+{}
+
void test_move()
{
{
@@ -510,6 +513,24 @@ void test_input_iterator()
BOOST_CHECK_EQUAL( ( int)3, vec[2] );
BOOST_CHECK_EQUAL( ( int)4, vec[3] );
}
+
+void test_invalid_result()
+{
+ bool catched = false;
+ coro::coroutine< int >::pull_type coro( f20);
+ BOOST_CHECK( ! coro);
+ try
+ {
+ int i = coro.get();
+ }
+ catch ( coro::invalid_result const& e)
+ {
+ boost::system::error_code ec = e.code();
+ BOOST_CHECK_EQUAL( coro::coroutine_errc::no_data, ec.value());
+ catched = true;
+ }
+ BOOST_CHECK( catched);
+}
#else
typedef coro::coroutine< void() > coro_void_void;
typedef coro::coroutine< int() > coro_int_void;
@@ -1039,6 +1060,8 @@ boost::unit_test::test_suite * init_unit_test_suite( int, char* [])
#ifndef BOOST_COROUTINES_UNIDIRECT
test->add( BOOST_TEST_CASE( & test_pre) );
test->add( BOOST_TEST_CASE( & test_post) );
+#else
+ test->add( BOOST_TEST_CASE( & test_invalid_result) );
#endif
test->add( BOOST_TEST_CASE( & test_ref) );
test->add( BOOST_TEST_CASE( & test_const_ref) );