mirror of
https://github.com/boostorg/context.git
synced 2026-01-19 04:02:17 +00:00
implement thread awareness in can_resume()
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -239,9 +240,14 @@ private:
|
||||
detail::fiber_context_ontop( detail::transfer_t);
|
||||
|
||||
detail::fcontext_t fctx_{ nullptr };
|
||||
std::thread::id * id_{ nullptr };
|
||||
|
||||
fiber_context( detail::fcontext_t fctx) noexcept :
|
||||
fctx_{ fctx } {
|
||||
if ( nullptr != fctx_) {
|
||||
id_ = reinterpret_cast< std::thread::id * >( static_cast< char* >( fctx_) + sizeof( std::thread::id) );
|
||||
*id_ = std::this_thread::get_id();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -255,13 +261,17 @@ public:
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber_context( std::allocator_arg_t, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber_context1< detail::fiber_context_record< fiber_context, StackAlloc, Fn > >(
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) },
|
||||
id_{ reinterpret_cast< std::thread::id * >( static_cast< char* >( fctx_) + sizeof( std::thread::id) ) } {
|
||||
*id_ = std::this_thread::get_id();
|
||||
}
|
||||
|
||||
template< typename StackAlloc, typename Fn >
|
||||
fiber_context( std::allocator_arg_t, preallocated palloc, StackAlloc && salloc, Fn && fn) :
|
||||
fctx_{ detail::create_fiber_context2< detail::fiber_context_record< fiber_context, StackAlloc, Fn > >(
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) } {
|
||||
palloc, std::forward< StackAlloc >( salloc), std::forward< Fn >( fn) ) },
|
||||
id_{ reinterpret_cast< std::thread::id * >( static_cast< char* >( fctx_) + sizeof( std::thread::id) ) } {
|
||||
*id_ = std::this_thread::get_id();
|
||||
}
|
||||
|
||||
#if defined(BOOST_USE_SEGMENTED_STACKS)
|
||||
@@ -315,10 +325,8 @@ public:
|
||||
|
||||
bool can_resume() noexcept {
|
||||
if ( ! empty() ) {
|
||||
// TODO:
|
||||
// *this has no owning thread
|
||||
// calling thread is the owning thread represented by *this
|
||||
return true;
|
||||
BOOST_ASSERT_MSG( nullptr != id_, "invalid thread id");
|
||||
return std::this_thread::get_id() == *id_;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -333,6 +341,7 @@ public:
|
||||
|
||||
void swap( fiber_context & other) noexcept {
|
||||
std::swap( fctx_, other.fctx_);
|
||||
std::swap( id_, other.id_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_EMBTC)
|
||||
|
||||
@@ -28,6 +28,7 @@ extern "C" {
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -81,6 +82,7 @@ struct BOOST_CONTEXT_DECL fiber_context_activation_record {
|
||||
std::function< fiber_context_activation_record*(fiber_context_activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
std::thread::id id{ std::this_thread::get_id() };
|
||||
#if defined(BOOST_USE_ASAN)
|
||||
void * fake_stack{ nullptr };
|
||||
void * stack_bottom{ nullptr };
|
||||
@@ -256,6 +258,7 @@ public:
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
id = std::thread::id{};
|
||||
std::move( c).resume();
|
||||
BOOST_ASSERT_MSG( false, "fiber_context already terminated");
|
||||
}
|
||||
@@ -466,10 +469,7 @@ public:
|
||||
|
||||
bool can_resume() noexcept {
|
||||
if ( ! empty() ) {
|
||||
// TODO:
|
||||
// *this has no owning thread
|
||||
// calling thread is the owning thread represented by *this
|
||||
return true;
|
||||
return std::this_thread::get_id() == ptr_->id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
@@ -62,6 +63,7 @@ struct BOOST_CONTEXT_DECL fiber_context_activation_record {
|
||||
std::function< fiber_context_activation_record*(fiber_context_activation_record*&) > ontop{};
|
||||
bool terminated{ false };
|
||||
bool force_unwind{ false };
|
||||
std::thread::id id{ std::this_thread::get_id() };
|
||||
|
||||
static fiber_context_activation_record *& current() noexcept;
|
||||
|
||||
@@ -193,6 +195,7 @@ public:
|
||||
ontop = nullptr;
|
||||
terminated = true;
|
||||
force_unwind = false;
|
||||
id = std::thread::id{};
|
||||
std::move( c).resume();
|
||||
BOOST_ASSERT_MSG( false, "fiber_context already terminated");
|
||||
}
|
||||
@@ -330,10 +333,7 @@ public:
|
||||
|
||||
bool can_resume() noexcept {
|
||||
if ( ! empty() ) {
|
||||
// TODO:
|
||||
// *this has no owning thread
|
||||
// calling thread is the owning thread represented by *this
|
||||
return true;
|
||||
return std::this_thread::get_id() == ptr_->id;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -524,6 +524,36 @@ void test_badcatch() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_can_resume() {
|
||||
int a;
|
||||
std::fiber_context f{
|
||||
[&a](std::fiber_context && f) {
|
||||
a=0;
|
||||
int b=1;
|
||||
for(;;){
|
||||
f = std::move( f).resume();
|
||||
int next=a+b;
|
||||
a=b;
|
||||
b=next;
|
||||
}
|
||||
return std::move( f);
|
||||
}};
|
||||
BOOST_CHECK( ! f.empty() );
|
||||
BOOST_CHECK( f.can_resume() );
|
||||
for ( int j = 0; j < 10; ++j) {
|
||||
f = std::move( f).resume();
|
||||
std::cout << a << " ";
|
||||
}
|
||||
BOOST_CHECK( ! f.empty() );
|
||||
BOOST_CHECK( f.can_resume() );
|
||||
BOOST_CHECK_EQUAL( 34, a);
|
||||
std::thread t{ [&f](){
|
||||
BOOST_CHECK( ! f.empty() );
|
||||
BOOST_CHECK( ! f.can_resume() );
|
||||
}};
|
||||
t.join();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_move();
|
||||
@@ -543,6 +573,7 @@ int main()
|
||||
#endif
|
||||
test_goodcatch();
|
||||
test_badcatch();
|
||||
test_can_resume();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user