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

9  

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

12  

13  
#include <mutex>
13  
#include <mutex>
14  

14  

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

16  

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

18  

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

22  

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

31  

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

37  

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

40  

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

45  

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

50  

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

55  

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

60  

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

69  

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

72  

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

78  

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

84  

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

89  

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

98  

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

100  

101  
#endif // BOOST_COROSIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
101  
#endif // BOOST_COROSIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP