Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions include/boost/corosio/native/detail/iocp/win_mutex.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ namespace boost::corosio::detail {
Each call to `lock()` or successful `try_lock()` must be
balanced by a corresponding call to `unlock()`.

When disabled via `set_enabled(false)`, all locking operations
become no-ops. This supports single-threaded (lockless) mode
where cross-thread posting is undefined behavior.

Satisfies the Lockable named requirement and is compatible
with `std::lock_guard`, `std::unique_lock`, and `std::scoped_lock`.
*/
Expand All @@ -46,23 +50,29 @@ class win_mutex
win_mutex(win_mutex const&) = delete;
win_mutex& operator=(win_mutex const&) = delete;

void set_enabled(bool v) noexcept { enabled_ = v; }
bool enabled() const noexcept { return enabled_; }

void lock() noexcept
{
::EnterCriticalSection(&cs_);
if (enabled_)
::EnterCriticalSection(&cs_);
}

void unlock() noexcept
{
::LeaveCriticalSection(&cs_);
if (enabled_)
::LeaveCriticalSection(&cs_);
}

bool try_lock() noexcept
{
return ::TryEnterCriticalSection(&cs_) != 0;
return !enabled_ || ::TryEnterCriticalSection(&cs_) != 0;
}

private:
::CRITICAL_SECTION cs_;
bool enabled_ = true;
};

} // namespace boost::corosio::detail
Expand Down
12 changes: 12 additions & 0 deletions include/boost/corosio/native/detail/iocp/win_scheduler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ class BOOST_COROSIO_DECL win_scheduler final
gqcs_timeout_ms_ = gqcs_timeout_ms;
}

/** Enable or disable single-threaded (lockless) mode.

When enabled, the dispatch mutex becomes a no-op.
Cross-thread post() is undefined behavior.
*/
void configure_single_threaded(bool v) noexcept
{
single_threaded_ = v;
dispatch_mutex_.set_enabled(!v);
}

/** Signal that an overlapped I/O operation is now pending.
Coordinates with do_one() via the ready_ CAS protocol. */
void on_pending(overlapped_op* op) const;
Expand All @@ -112,6 +123,7 @@ class BOOST_COROSIO_DECL win_scheduler final
long stop_event_posted_;
mutable long dispatch_required_;
unsigned long gqcs_timeout_ms_ = 500;
bool single_threaded_ = false;

mutable win_mutex dispatch_mutex_;
mutable op_queue completed_ops_;
Expand Down
6 changes: 4 additions & 2 deletions src/corosio/src/io_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,10 @@ apply_scheduler_options(
#endif

#if BOOST_COROSIO_HAS_IOCP
static_cast<detail::win_scheduler&>(sched).configure_iocp(
opts.gqcs_timeout_ms);
auto& iocp_sched = static_cast<detail::win_scheduler&>(sched);
iocp_sched.configure_iocp(opts.gqcs_timeout_ms);
if (opts.single_threaded)
iocp_sched.configure_single_threaded(true);
#endif

(void)sched;
Expand Down
Loading