1 +
//
 
2 +
// Copyright (c) 2026 Michael Vandeberg
 
3 +
//
 
4 +
// Distributed under the Boost Software License, Version 1.0. (See accompanying
 
5 +
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 
6 +
//
 
7 +
// Official repository: https://github.com/cppalliance/corosio
 
8 +
//
 
9 +

 
10 +
#ifndef BOOST_COROSIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
 
11 +
#define BOOST_COROSIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
 
12 +

 
13 +
#include <mutex>
 
14 +

 
15 +
namespace boost::corosio::detail {
 
16 +

 
17 +
/* Mutex wrapper that becomes a no-op when disabled.
 
18 +

 
19 +
   When enabled (the default), lock/unlock delegate to an
 
20 +
   underlying std::mutex. When disabled, all operations are
 
21 +
   no-ops. The enabled flag is fixed after construction.
 
22 +

 
23 +
   scoped_lock wraps std::unique_lock<std::mutex> internally
 
24 +
   so that condvar wait paths (which require the real lock
 
25 +
   type) compile and work in multi-threaded mode.
 
26 +
*/
 
27 +
class conditionally_enabled_mutex
 
28 +
{
 
29 +
    std::mutex mutex_;
 
30 +
    bool enabled_;
 
31 +

 
32 +
public:
 
33 +
    explicit conditionally_enabled_mutex(bool enabled = true) noexcept
 
34 +
        : enabled_(enabled)
 
35 +
    {
 
36 +
    }
 
37 +

 
38 +
    conditionally_enabled_mutex(conditionally_enabled_mutex const&)            = delete;
 
39 +
    conditionally_enabled_mutex& operator=(conditionally_enabled_mutex const&) = delete;
 
40 +

 
41 +
    bool enabled() const noexcept
 
42 +
    {
 
43 +
        return enabled_;
 
44 +
    }
 
45 +

 
46 +
    void set_enabled(bool v) noexcept
 
47 +
    {
 
48 +
        enabled_ = v;
 
49 +
    }
 
50 +

 
51 +
    // Lockable interface — allows std::lock_guard<conditionally_enabled_mutex>
 
52 +
    void lock() { if (enabled_) mutex_.lock(); }
 
53 +
    void unlock() { if (enabled_) mutex_.unlock(); }
 
54 +
    bool try_lock() { return !enabled_ || mutex_.try_lock(); }
 
55 +

 
56 +
    class scoped_lock
 
57 +
    {
 
58 +
        std::unique_lock<std::mutex> lock_;
 
59 +
        bool enabled_;
 
60 +

 
61 +
    public:
 
62 +
        explicit scoped_lock(conditionally_enabled_mutex& m)
 
63 +
            : lock_(m.mutex_, std::defer_lock)
 
64 +
            , enabled_(m.enabled_)
 
65 +
        {
 
66 +
            if (enabled_)
 
67 +
                lock_.lock();
 
68 +
        }
 
69 +

 
70 +
        scoped_lock(scoped_lock const&)            = delete;
 
71 +
        scoped_lock& operator=(scoped_lock const&) = delete;
 
72 +

 
73 +
        void lock()
 
74 +
        {
 
75 +
            if (enabled_)
 
76 +
                lock_.lock();
 
77 +
        }
 
78 +

 
79 +
        void unlock()
 
80 +
        {
 
81 +
            if (enabled_)
 
82 +
                lock_.unlock();
 
83 +
        }
 
84 +

 
85 +
        bool owns_lock() const noexcept
 
86 +
        {
 
87 +
            return enabled_ && lock_.owns_lock();
 
88 +
        }
 
89 +

 
90 +
        // Access the underlying unique_lock for condvar wait().
 
91 +
        // Only called when locking is enabled.
 
92 +
        std::unique_lock<std::mutex>& underlying() noexcept
 
93 +
        {
 
94 +
            return lock_;
 
95 +
        }
 
96 +
    };
 
97 +
};
 
98 +

 
99 +
} // namespace boost::corosio::detail
 
100 +

 
101 +
#endif // BOOST_COROSIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP