File: juce_CriticalSection.h

package info (click to toggle)
juce 6.1.3~ds0-1~exp1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 61,612 kB
  • sloc: cpp: 431,694; java: 2,592; ansic: 797; xml: 259; sh: 164; python: 126; makefile: 64
file content (262 lines) | stat: -rw-r--r-- 8,739 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
  ==============================================================================

   This file is part of the JUCE library.
   Copyright (c) 2020 - Raw Material Software Limited

   JUCE is an open source library subject to commercial or open-source
   licensing.

   The code included in this file is provided under the terms of the ISC license
   http://www.isc.org/downloads/software-support-policy/isc-license. Permission
   To use, copy, modify, and/or distribute this software for any purpose with or
   without fee is hereby granted provided that the above copyright notice and
   this permission notice appear in all copies.

   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
   DISCLAIMED.

  ==============================================================================
*/

namespace juce
{

//==============================================================================
/**
    A re-entrant mutex.

    A CriticalSection acts as a re-entrant mutex object. The best way to lock and unlock
    one of these is by using RAII in the form of a local ScopedLock object - have a look
    through the codebase for many examples of how to do this.

    In almost all cases you'll want to declare your CriticalSection as a member variable.
    Occasionally you may want to declare one as a static variable, but in that case the usual
    C++ static object order-of-construction warnings should be heeded.

    @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock

    @tags{Core}
*/
class JUCE_API  CriticalSection
{
public:
    //==============================================================================
    /** Creates a CriticalSection object. */
    CriticalSection() noexcept;

    /** Destructor.
        If the critical section is deleted whilst locked, any subsequent behaviour
        is unpredictable.
    */
    ~CriticalSection() noexcept;

    //==============================================================================
    /** Acquires the lock.

        If the lock is already held by the caller thread, the method returns immediately.
        If the lock is currently held by another thread, this will wait until it becomes free.

        It's strongly recommended that you never call this method directly - instead use the
        ScopedLock class to manage the locking using an RAII pattern instead.

        @see exit, tryEnter, ScopedLock
    */
    void enter() const noexcept;

    /** Attempts to lock this critical section without blocking.

        This method behaves identically to CriticalSection::enter, except that the caller thread
        does not wait if the lock is currently held by another thread but returns false immediately.

        @returns false if the lock is currently held by another thread, true otherwise.
        @see enter
    */
    bool tryEnter() const noexcept;

    /** Releases the lock.

        If the caller thread hasn't got the lock, this can have unpredictable results.

        If the enter() method has been called multiple times by the thread, each
        call must be matched by a call to exit() before other threads will be allowed
        to take over the lock.

        @see enter, ScopedLock
    */
    void exit() const noexcept;


    //==============================================================================
    /** Provides the type of scoped lock to use with a CriticalSection. */
    using ScopedLockType = GenericScopedLock<CriticalSection>;

    /** Provides the type of scoped unlocker to use with a CriticalSection. */
    using ScopedUnlockType = GenericScopedUnlock<CriticalSection>;

    /** Provides the type of scoped try-locker to use with a CriticalSection. */
    using ScopedTryLockType = GenericScopedTryLock<CriticalSection>;


private:
    //==============================================================================
   #if JUCE_WINDOWS
    // To avoid including windows.h in the public JUCE headers, we'll just allocate
    // a block of memory here that's big enough to be used internally as a windows
    // CRITICAL_SECTION structure.
    #if JUCE_64BIT
     std::aligned_storage<44, 8>::type lock;
    #else
     std::aligned_storage<24, 8>::type lock;
    #endif
   #else
    mutable pthread_mutex_t lock;
   #endif

    JUCE_DECLARE_NON_COPYABLE (CriticalSection)
};


//==============================================================================
/**
    A class that can be used in place of a real CriticalSection object, but which
    doesn't perform any locking.

    This is currently used by some templated classes, and most compilers should
    manage to optimise it out of existence.

    @see CriticalSection, Array, OwnedArray, ReferenceCountedArray

    @tags{Core}
*/
class JUCE_API  DummyCriticalSection
{
public:
    inline DummyCriticalSection() = default;
    inline ~DummyCriticalSection() = default;

    inline void enter() const noexcept          {}
    inline bool tryEnter() const noexcept       { return true; }
    inline void exit() const noexcept           {}

    //==============================================================================
    /** A dummy scoped-lock type to use with a dummy critical section. */
    struct ScopedLockType
    {
        ScopedLockType (const DummyCriticalSection&) noexcept {}
    };

    /** A dummy scoped-unlocker type to use with a dummy critical section. */
    using ScopedUnlockType = ScopedLockType;

private:
    JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection)
};

//==============================================================================
/**
    Automatically locks and unlocks a CriticalSection object.

    You can use a ScopedLock as a local variable to provide RAII-based locking of a CriticalSection.

    e.g. @code

    struct MyObject
    {
        CriticalSection objectLock;

        // assuming that this example function will be called by multiple threads
        void foo()
        {
            const ScopedLock myScopedLock (objectLock);

            // objectLock is now locked..

            ...do some thread-safe work here...

            // ..and objectLock gets unlocked here, as myScopedLock goes out of
            // scope at the end of the block
        }
    };
    @endcode

    @see CriticalSection, ScopedUnlock
*/
using ScopedLock = CriticalSection::ScopedLockType;

//==============================================================================
/**
    Automatically unlocks and re-locks a CriticalSection object.

    This is the reverse of a ScopedLock object - instead of locking the critical
    section for the lifetime of this object, it unlocks it.

    Make sure you don't try to unlock critical sections that aren't actually locked!

    e.g. @code

    struct MyObject
    {
        CriticalSection objectLock;

        void foo()
        {
            {
                const ScopedLock myScopedLock (objectLock);

                // objectLock is now locked..

                {
                    ScopedUnlock myUnlocker (objectLock);

                    // ..and now unlocked..
                }

                // ..and now locked again..
            }

            // ..and finally unlocked.
        }
    };
    @endcode

    @see CriticalSection, ScopedLock
*/
using ScopedUnlock = CriticalSection::ScopedUnlockType;

//==============================================================================
/**
    Automatically tries to lock and unlock a CriticalSection object.

    Use one of these as a local variable to control access to a CriticalSection.

    e.g. @code

    struct MyObject
    {
        CriticalSection objectLock;

        void foo()
        {
            const ScopedTryLock myScopedTryLock (objectLock);

            // Unlike using a ScopedLock, this may fail to actually get the lock, so you
            // must call the isLocked() method before making any assumptions..
            if (myScopedTryLock.isLocked())
            {
               ...safely do some work...
            }
            else
            {
                // If we get here, then our attempt at locking failed because another thread had already locked it..
            }
        }
    };
    @endcode

    @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock
*/
using ScopedTryLock = CriticalSection::ScopedTryLockType;

} // namespace juce