Skip to content

Commit e57eada

Browse files
committed
Add single-threaded (lockless) mode to IOCP backend
1 parent 0cf9f49 commit e57eada

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

include/boost/corosio/native/detail/iocp/win_mutex.hpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ namespace boost::corosio::detail {
2727
Each call to `lock()` or successful `try_lock()` must be
2828
balanced by a corresponding call to `unlock()`.
2929
30+
When disabled via `set_enabled(false)`, all locking operations
31+
become no-ops. This supports single-threaded (lockless) mode
32+
where cross-thread posting is undefined behavior.
33+
3034
Satisfies the Lockable named requirement and is compatible
3135
with `std::lock_guard`, `std::unique_lock`, and `std::scoped_lock`.
3236
*/
@@ -46,23 +50,29 @@ class win_mutex
4650
win_mutex(win_mutex const&) = delete;
4751
win_mutex& operator=(win_mutex const&) = delete;
4852

53+
void set_enabled(bool v) noexcept { enabled_ = v; }
54+
bool enabled() const noexcept { return enabled_; }
55+
4956
void lock() noexcept
5057
{
51-
::EnterCriticalSection(&cs_);
58+
if (enabled_)
59+
::EnterCriticalSection(&cs_);
5260
}
5361

5462
void unlock() noexcept
5563
{
56-
::LeaveCriticalSection(&cs_);
64+
if (enabled_)
65+
::LeaveCriticalSection(&cs_);
5766
}
5867

5968
bool try_lock() noexcept
6069
{
61-
return ::TryEnterCriticalSection(&cs_) != 0;
70+
return !enabled_ || ::TryEnterCriticalSection(&cs_) != 0;
6271
}
6372

6473
private:
6574
::CRITICAL_SECTION cs_;
75+
bool enabled_ = true;
6676
};
6777

6878
} // namespace boost::corosio::detail

include/boost/corosio/native/detail/iocp/win_scheduler.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,17 @@ class BOOST_COROSIO_DECL win_scheduler final
8989
gqcs_timeout_ms_ = gqcs_timeout_ms;
9090
}
9191

92+
/** Enable or disable single-threaded (lockless) mode.
93+
94+
When enabled, the dispatch mutex becomes a no-op.
95+
Cross-thread post() is undefined behavior.
96+
*/
97+
void configure_single_threaded(bool v) noexcept
98+
{
99+
single_threaded_ = v;
100+
dispatch_mutex_.set_enabled(!v);
101+
}
102+
92103
/** Signal that an overlapped I/O operation is now pending.
93104
Coordinates with do_one() via the ready_ CAS protocol. */
94105
void on_pending(overlapped_op* op) const;
@@ -113,6 +124,7 @@ class BOOST_COROSIO_DECL win_scheduler final
113124
long stop_event_posted_;
114125
mutable long dispatch_required_;
115126
unsigned long gqcs_timeout_ms_ = 500;
127+
bool single_threaded_ = false;
116128

117129
mutable win_mutex dispatch_mutex_;
118130
mutable op_queue completed_ops_;

src/corosio/src/io_context.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,10 @@ apply_scheduler_options(
153153
#endif
154154

155155
#if BOOST_COROSIO_HAS_IOCP
156-
static_cast<detail::win_scheduler&>(sched).configure_iocp(
157-
opts.gqcs_timeout_ms);
156+
auto& iocp_sched = static_cast<detail::win_scheduler&>(sched);
157+
iocp_sched.configure_iocp(opts.gqcs_timeout_ms);
158+
if (opts.single_threaded)
159+
iocp_sched.configure_single_threaded(true);
158160
#endif
159161

160162
(void)sched;

0 commit comments

Comments
 (0)