2
0
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:
Oliver Kowalke
2023-04-21 07:27:07 +02:00
parent ab27b1bdad
commit f8b3d409fb
4 changed files with 54 additions and 14 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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();
}