Skip to content

Commit

Permalink
Merge branch 'boostorg:develop' into zig-pkg
Browse files Browse the repository at this point in the history
  • Loading branch information
kassane authored Oct 16, 2023
2 parents cdba86c + 88b8304 commit 96eba0e
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 26 deletions.
5 changes: 5 additions & 0 deletions include/boost/fiber/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
#include <boost/fiber/segmented_stack.hpp>
#include <boost/fiber/type.hpp>
#include <boost/fiber/waker.hpp>
#include <boost/fiber/stack_allocator_wrapper.hpp>
#include <boost/fiber/algo/algorithm.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
Expand Down Expand Up @@ -223,6 +225,9 @@ class BOOST_FIBERS_DECL context {
}
};

// Returns true if the thread could be initialize, false otherwise (it was already initialized previously).
static bool initialize_thread(algo::algorithm::ptr_t algo, stack_allocator_wrapper&& salloc) noexcept;

static context * active() noexcept;

static void reset_active() noexcept;
Expand Down
9 changes: 7 additions & 2 deletions include/boost/fiber/operations.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <boost/fiber/detail/convert.hpp>
#include <boost/fiber/fiber.hpp>
#include <boost/fiber/scheduler.hpp>
#include <boost/fiber/stack_allocator_wrapper.hpp>

#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
Expand Down Expand Up @@ -75,10 +76,14 @@ bool has_ready_fibers() noexcept {
return boost::fibers::context::active()->get_scheduler()->has_ready_fibers();
}

// Returns true if the thread could be initialize, false otherwise (it was already initialized previously).
inline bool initialize_thread(algo::algorithm::ptr_t algo, stack_allocator_wrapper&& salloc) noexcept {
return boost::fibers::context::initialize_thread(algo, std::move(salloc));
}

template< typename SchedAlgo, typename ... Args >
void use_scheduling_algorithm( Args && ... args) noexcept {
boost::fibers::context::active()->get_scheduler()
->set_algo( new SchedAlgo( std::forward< Args >( args) ... ) );
initialize_thread(new SchedAlgo(std::forward< Args >( args) ... ), make_stack_allocator_wrapper<boost::fibers::default_stack>());
}

}}
Expand Down
2 changes: 1 addition & 1 deletion include/boost/fiber/scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class BOOST_FIBERS_DECL scheduler {
void sleep2ready_() noexcept;

public:
scheduler() noexcept;
scheduler(algo::algorithm::ptr_t algo) noexcept;

scheduler( scheduler const&) = delete;
scheduler & operator=( scheduler const&) = delete;
Expand Down
94 changes: 94 additions & 0 deletions include/boost/fiber/stack_allocator_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#ifndef BOOST_FIBERS_STACK_ALLOCATOR_WRAPPER_H
#define BOOST_FIBERS_STACK_ALLOCATOR_WRAPPER_H

#include <memory>

#include <boost/fiber/detail/config.hpp>
#include <boost/context/stack_context.hpp>
#include <boost/fiber/fixedsize_stack.hpp>
#include <boost/fiber/segmented_stack.hpp>

namespace boost {
namespace fibers {
namespace detail {
class BOOST_FIBERS_DECL polymorphic_stack_allocator_base {
public:
polymorphic_stack_allocator_base() = default;

virtual ~polymorphic_stack_allocator_base() = default;

polymorphic_stack_allocator_base(const polymorphic_stack_allocator_base&) = delete;
polymorphic_stack_allocator_base& operator=(const polymorphic_stack_allocator_base&) = delete;

polymorphic_stack_allocator_base(polymorphic_stack_allocator_base&&) = delete;
polymorphic_stack_allocator_base& operator=(polymorphic_stack_allocator_base&&) = delete;

virtual boost::context::stack_context allocate() = 0;

virtual void deallocate(boost::context::stack_context& sctx) = 0;
};

template< typename StackAllocator >
class BOOST_FIBERS_DECL polymorphic_stack_allocator_impl final : public polymorphic_stack_allocator_base {
public:
template<typename ... Args >
polymorphic_stack_allocator_impl( Args && ... args )
:_allocator(std::forward< Args >( args) ... )
{}

~polymorphic_stack_allocator_impl() = default;

boost::context::stack_context allocate() override
{
return _allocator.allocate();
}

void deallocate(boost::context::stack_context& sctx) override
{
_allocator.deallocate(sctx);
}

private:
StackAllocator _allocator;
};
}

class BOOST_FIBERS_DECL stack_allocator_wrapper final {
public:
stack_allocator_wrapper(std::unique_ptr<detail::polymorphic_stack_allocator_base> allocator)
:_allocator(std::move(allocator))
{}

~stack_allocator_wrapper() = default;

stack_allocator_wrapper(const stack_allocator_wrapper&) = delete;
stack_allocator_wrapper& operator=(const stack_allocator_wrapper&) = delete;

stack_allocator_wrapper(stack_allocator_wrapper&&) = default;
stack_allocator_wrapper& operator=(stack_allocator_wrapper&&) = default;

boost::context::stack_context allocate()
{
return _allocator->allocate();
}

void deallocate(boost::context::stack_context& sctx)
{
_allocator->deallocate(sctx);
}

private:
std::unique_ptr<detail::polymorphic_stack_allocator_base> _allocator;
};

template <typename StackAllocator, typename ... Args>
BOOST_FIBERS_DECL stack_allocator_wrapper make_stack_allocator_wrapper(Args && ... args)
{
return stack_allocator_wrapper(
std::unique_ptr<detail::polymorphic_stack_allocator_base>(
new detail::polymorphic_stack_allocator_impl<StackAllocator>(std::forward< Args >( args) ... )));
}
}
}

#endif
82 changes: 62 additions & 20 deletions src/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "boost/fiber/exceptions.hpp"
#include "boost/fiber/scheduler.hpp"
#include "boost/fiber/algo/round_robin.hpp"

#ifdef BOOST_HAS_ABI_HEADERS
# include BOOST_ABI_PREFIX
Expand Down Expand Up @@ -41,18 +42,17 @@ class dispatcher_context final : public context {
}

public:
dispatcher_context( boost::context::preallocated const& palloc, default_stack && salloc) :
dispatcher_context( boost::context::preallocated const& palloc, stack_allocator_wrapper&& salloc) :
context{ 0, type::dispatcher_context, launch::post } {
c_ = boost::context::fiber{ std::allocator_arg, palloc, salloc,
c_ = boost::context::fiber{ std::allocator_arg, palloc, std::move(salloc),
std::bind( & dispatcher_context::run_, this, std::placeholders::_1) };
#if (defined(BOOST_USE_UCONTEXT)||defined(BOOST_USE_WINFIB))
c_ = std::move( c_).resume();
#endif
}
};

static intrusive_ptr< context > make_dispatcher_context() {
default_stack salloc; // use default satck-size
static intrusive_ptr< context > make_dispatcher_context(stack_allocator_wrapper&& salloc) {
auto sctx = salloc.allocate();
// reserve space for control structure
void * storage = reinterpret_cast< void * >(
Expand All @@ -72,36 +72,78 @@ struct context_initializer {
static thread_local context * active_;
static thread_local std::size_t counter_;

context_initializer() {
using default_scheduler = algo::round_robin;

template< typename ... Args >
context_initializer(Args && ... args) {
if ( 0 == counter_++) {
// main fiber context of this thread
context * main_ctx = new main_context{};
// scheduler of this thread
auto sched = new scheduler{};
// attach main context to scheduler
sched->attach_main_context( main_ctx);
// create and attach dispatcher context to scheduler
sched->attach_dispatcher_context( make_dispatcher_context() );
// make main context to active context
active_ = main_ctx;
initialize(std::forward< Args >( args) ... );
}
}

~context_initializer() {
if ( 0 == --counter_) {
context * main_ctx = active_;
BOOST_ASSERT( main_ctx->is_context( type::main_context) );
scheduler * sched = main_ctx->get_scheduler();
delete sched;
delete main_ctx;
deinitialize();
}
}

void initialize()
{
initialize(new default_scheduler(), make_stack_allocator_wrapper<default_stack>());
}

void initialize(algo::algorithm::ptr_t algo, stack_allocator_wrapper&& salloc)
{
// main fiber context of this thread
context * main_ctx = new main_context{};
// scheduler of this thread
auto sched = new scheduler(algo);
// attach main context to scheduler
sched->attach_main_context( main_ctx);
// create and attach dispatcher context to scheduler
sched->attach_dispatcher_context( make_dispatcher_context(std::move(salloc)) );
// make main context to active context
active_ = main_ctx;
}

void deinitialize()
{
context * main_ctx = active_;
BOOST_ASSERT( main_ctx->is_context( type::main_context) );
scheduler * sched = main_ctx->get_scheduler();
delete sched;
delete main_ctx;
}
};

// zero-initialization
thread_local context * context_initializer::active_{ nullptr };
thread_local std::size_t context_initializer::counter_{ 0 };

bool context::initialize_thread(algo::algorithm::ptr_t algo, stack_allocator_wrapper&& salloc) noexcept
{
if (context_initializer::counter_ == 0)
{
// Initilization is not done yet, so do it now with a local variable
// context_initializer which will decrease the counter when leaving this function.
context_initializer ctx_initializer(algo, std::move(salloc));

// Now call active() to register a thread local context_initializer which will
// ensure resources are free'ed when the thread exits.
active();

return true;
}
else
{
// It's too late already to initialize the dispatcher stack allocator, still we can update
// the algo.
active()->get_scheduler()->set_algo(algo);

return false;
}
}

context *
context::active() noexcept {
// initialized the first time control passes; per thread
Expand Down
5 changes: 2 additions & 3 deletions src/scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

#include <boost/assert.hpp>

#include "boost/fiber/algo/round_robin.hpp"
#include "boost/fiber/context.hpp"
#include "boost/fiber/exceptions.hpp"

Expand Down Expand Up @@ -94,8 +93,8 @@ scheduler::sleep2ready_() noexcept {
}
}

scheduler::scheduler() noexcept :
algo_{ new algo::round_robin() } {
scheduler::scheduler(algo::algorithm::ptr_t algo) noexcept :
algo_{algo} {
}

scheduler::~scheduler() {
Expand Down

0 comments on commit 96eba0e

Please sign in to comment.