| @@ -1069,8 +1069,8 @@ | |||
| 9E622C38E4BD511B6ABBF7AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ReadWriteLock.h; path = ../../src/threads/juce_ReadWriteLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 6734838B47EF0D9ACEE571CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedLock.h; path = ../../src/threads/juce_ScopedLock.h; sourceTree = SOURCE_ROOT; }; | |||
| F00BDEF5CE2B281CBE2E89A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedReadLock.h; path = ../../src/threads/juce_ScopedReadLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 18AD809DE191E1CF42D0BF53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedTryLock.h; path = ../../src/threads/juce_ScopedTryLock.h; sourceTree = SOURCE_ROOT; }; | |||
| C5F20B02D7843F3C5ABEDFD4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedWriteLock.h; path = ../../src/threads/juce_ScopedWriteLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 1FD1C9A3D2DB64C825FDAC8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_SpinLock.h; path = ../../src/threads/juce_SpinLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 4D60F7F748CF6702D1E45960 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Thread.cpp; path = ../../src/threads/juce_Thread.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EFE26D4E1E2B92828DBA3A99 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Thread.h; path = ../../src/threads/juce_Thread.h; sourceTree = SOURCE_ROOT; }; | |||
| EF06213027EA3F7C54EE0F18 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ThreadPool.cpp; path = ../../src/threads/juce_ThreadPool.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1904,8 +1904,8 @@ | |||
| 9E622C38E4BD511B6ABBF7AA, | |||
| 6734838B47EF0D9ACEE571CD, | |||
| F00BDEF5CE2B281CBE2E89A2, | |||
| 18AD809DE191E1CF42D0BF53, | |||
| C5F20B02D7843F3C5ABEDFD4, | |||
| 1FD1C9A3D2DB64C825FDAC8B, | |||
| 4D60F7F748CF6702D1E45960, | |||
| EFE26D4E1E2B92828DBA3A99, | |||
| EF06213027EA3F7C54EE0F18, | |||
| @@ -993,8 +993,8 @@ | |||
| <File RelativePath="..\..\src\threads\juce_ReadWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedReadLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedTryLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_SpinLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.cpp"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ThreadPool.cpp"/> | |||
| @@ -993,8 +993,8 @@ | |||
| <File RelativePath="..\..\src\threads\juce_ReadWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedReadLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedTryLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_SpinLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.cpp"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ThreadPool.cpp"/> | |||
| @@ -995,8 +995,8 @@ | |||
| <File RelativePath="..\..\src\threads\juce_ReadWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedReadLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedTryLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ScopedWriteLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_SpinLock.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.cpp"/> | |||
| <File RelativePath="..\..\src\threads\juce_Thread.h"/> | |||
| <File RelativePath="..\..\src\threads\juce_ThreadPool.cpp"/> | |||
| @@ -800,8 +800,8 @@ | |||
| <ClInclude Include="..\..\src\threads\juce_ReadWriteLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedReadLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedTryLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedWriteLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_SpinLock.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_Thread.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_ThreadPool.h"/> | |||
| <ClInclude Include="..\..\src\threads\juce_TimeSliceThread.h"/> | |||
| @@ -2334,10 +2334,10 @@ | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedReadLock.h"> | |||
| <Filter>Juce\Source\threads</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedTryLock.h"> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedWriteLock.h"> | |||
| <Filter>Juce\Source\threads</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\threads\juce_ScopedWriteLock.h"> | |||
| <ClInclude Include="..\..\src\threads\juce_SpinLock.h"> | |||
| <Filter>Juce\Source\threads</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\threads\juce_Thread.h"> | |||
| @@ -1069,8 +1069,8 @@ | |||
| 9E622C38E4BD511B6ABBF7AA = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ReadWriteLock.h; path = ../../src/threads/juce_ReadWriteLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 6734838B47EF0D9ACEE571CD = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedLock.h; path = ../../src/threads/juce_ScopedLock.h; sourceTree = SOURCE_ROOT; }; | |||
| F00BDEF5CE2B281CBE2E89A2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedReadLock.h; path = ../../src/threads/juce_ScopedReadLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 18AD809DE191E1CF42D0BF53 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedTryLock.h; path = ../../src/threads/juce_ScopedTryLock.h; sourceTree = SOURCE_ROOT; }; | |||
| C5F20B02D7843F3C5ABEDFD4 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_ScopedWriteLock.h; path = ../../src/threads/juce_ScopedWriteLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 1FD1C9A3D2DB64C825FDAC8B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_SpinLock.h; path = ../../src/threads/juce_SpinLock.h; sourceTree = SOURCE_ROOT; }; | |||
| 4D60F7F748CF6702D1E45960 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Thread.cpp; path = ../../src/threads/juce_Thread.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EFE26D4E1E2B92828DBA3A99 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Thread.h; path = ../../src/threads/juce_Thread.h; sourceTree = SOURCE_ROOT; }; | |||
| EF06213027EA3F7C54EE0F18 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_ThreadPool.cpp; path = ../../src/threads/juce_ThreadPool.cpp; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1904,8 +1904,8 @@ | |||
| 9E622C38E4BD511B6ABBF7AA, | |||
| 6734838B47EF0D9ACEE571CD, | |||
| F00BDEF5CE2B281CBE2E89A2, | |||
| 18AD809DE191E1CF42D0BF53, | |||
| C5F20B02D7843F3C5ABEDFD4, | |||
| 1FD1C9A3D2DB64C825FDAC8B, | |||
| 4D60F7F748CF6702D1E45960, | |||
| EFE26D4E1E2B92828DBA3A99, | |||
| EF06213027EA3F7C54EE0F18, | |||
| @@ -1541,10 +1541,9 @@ | |||
| file="src/threads/juce_ScopedLock.h"/> | |||
| <FILE id="4fVPnhFxo" name="juce_ScopedReadLock.h" compile="0" resource="0" | |||
| file="src/threads/juce_ScopedReadLock.h"/> | |||
| <FILE id="3YrDBGCt7" name="juce_ScopedTryLock.h" compile="0" resource="0" | |||
| file="src/threads/juce_ScopedTryLock.h"/> | |||
| <FILE id="ZzfHTAct1" name="juce_ScopedWriteLock.h" compile="0" resource="0" | |||
| file="src/threads/juce_ScopedWriteLock.h"/> | |||
| <FILE id="B67j1G" name="juce_SpinLock.h" compile="0" resource="0" file="src/threads/juce_SpinLock.h"/> | |||
| <FILE id="91WC4L0ai" name="juce_Thread.cpp" compile="1" resource="0" | |||
| file="src/threads/juce_Thread.cpp"/> | |||
| <FILE id="g4jLEfRco" name="juce_Thread.h" compile="0" resource="0" | |||
| @@ -244672,10 +244672,7 @@ void MessageManager::doPlatformSpecificShutdown() | |||
| // compiled on its own). | |||
| #if JUCE_INCLUDED_FILE | |||
| static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| NEWTEXTMETRICEXW*, | |||
| int type, | |||
| LPARAM lParam) | |||
| static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| @@ -244687,10 +244684,7 @@ static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| return 1; | |||
| } | |||
| static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| NEWTEXTMETRICEXW*, | |||
| int type, | |||
| LPARAM lParam) | |||
| static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| @@ -244703,7 +244697,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| lf.lfPitchAndFamily = FF_DONTCARE; | |||
| const String fontName (lpelfe->elfLogFont.lfFaceName); | |||
| fontName.copyToUTF16 (lf.lfFaceName, LF_FACESIZE - 1); | |||
| fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); | |||
| HDC dc = CreateCompatibleDC (0); | |||
| EnumFontFamiliesEx (dc, &lf, | |||
| @@ -244728,7 +244722,6 @@ const StringArray Font::findAllTypefaceNames() | |||
| lf.lfCharSet = DEFAULT_CHARSET; | |||
| lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lf.lfPitchAndFamily = FF_DONTCARE; | |||
| lf.lfFaceName[0] = 0; | |||
| EnumFontFamiliesEx (dc, &lf, | |||
| (FONTENUMPROCW) &wfontEnum1, | |||
| @@ -244794,18 +244787,18 @@ public: | |||
| SetMapperFlags (dc, 0); | |||
| SetMapMode (dc, MM_TEXT); | |||
| LOGFONTW lfw = { 0 }; | |||
| lfw.lfCharSet = DEFAULT_CHARSET; | |||
| lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lfw.lfOutPrecision = OUT_OUTLINE_PRECIS; | |||
| lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |||
| lfw.lfQuality = PROOF_QUALITY; | |||
| lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE); | |||
| lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL; | |||
| fontName.copyToUTF16 (lfw.lfFaceName, LF_FACESIZE - 1); | |||
| LOGFONTW lf = { 0 }; | |||
| lf.lfCharSet = DEFAULT_CHARSET; | |||
| lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lf.lfOutPrecision = OUT_OUTLINE_PRECIS; | |||
| lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |||
| lf.lfQuality = PROOF_QUALITY; | |||
| lf.lfItalic = (BYTE) (italic ? TRUE : FALSE); | |||
| lf.lfWeight = bold ? FW_BOLD : FW_NORMAL; | |||
| lf.lfHeight = size > 0 ? size : -256; | |||
| fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); | |||
| lfw.lfHeight = size > 0 ? size : -256; | |||
| HFONT standardSizedFont = CreateFontIndirect (&lfw); | |||
| HFONT standardSizedFont = CreateFontIndirect (&lf); | |||
| if (standardSizedFont != 0) | |||
| { | |||
| @@ -244818,8 +244811,8 @@ public: | |||
| OUTLINETEXTMETRIC otm; | |||
| if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0) | |||
| { | |||
| lfw.lfHeight = -(int) otm.otmEMSquare; | |||
| fontH = CreateFontIndirect (&lfw); | |||
| lf.lfHeight = -(int) otm.otmEMSquare; | |||
| fontH = CreateFontIndirect (&lf); | |||
| SelectObject (dc, fontH); | |||
| DeleteObject (standardSizedFont); | |||
| @@ -73,7 +73,7 @@ namespace JuceDummyNamespace {} | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 63 | |||
| #define JUCE_BUILDNUMBER 64 | |||
| /** Current Juce version number. | |||
| @@ -6454,10 +6454,210 @@ public: | |||
| #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| #define __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| #ifndef DOXYGEN | |||
| class ScopedLock; | |||
| class ScopedUnlock; | |||
| #endif | |||
| /*** Start of inlined file: juce_ScopedLock.h ***/ | |||
| #ifndef __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| #define __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| /** | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see GenericScopedUnlock, CriticalSection, SpinLock, ScopedLock, ScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedLock | |||
| { | |||
| public: | |||
| /** Creates a GenericScopedLock. | |||
| As soon as it is created, this will acquire the lock, and when the GenericScopedLock | |||
| object is deleted, the lock will be released. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedLock (const LockType& lock) throw() : lock_ (lock) { lock.enter(); } | |||
| /** Destructor. | |||
| The lock will be released when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, otherwise there are | |||
| no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedLock() throw() { lock_.exit(); } | |||
| private: | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedLock); | |||
| }; | |||
| /** | |||
| Automatically unlocks and re-locks a mutex object. | |||
| This is the reverse of a GenericScopedLock object - instead of locking the mutex | |||
| for the lifetime of this object, it unlocks it. | |||
| Make sure you don't try to unlock mutexes that aren't actually locked! | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ... do some stuff with it locked .. | |||
| while (xyz) | |||
| { | |||
| ... do some stuff with it locked .. | |||
| const GenericScopedUnlock<CriticalSection> unlocker (myCriticalSection); | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| ...do some stuff with it unlocked ... | |||
| } | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see GenericScopedLock, CriticalSection, ScopedLock, ScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedUnlock | |||
| { | |||
| public: | |||
| /** Creates a GenericScopedUnlock. | |||
| As soon as it is created, this will unlock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| be re-locked. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedUnlock (const LockType& lock) throw() : lock_ (lock) { lock.exit(); } | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedUnlock() throw() { lock_.enter(); } | |||
| private: | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedUnlock); | |||
| }; | |||
| /** | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedTryLock<CriticalSection> myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, GenericScopedLock, GenericScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedTryLock | |||
| { | |||
| public: | |||
| /** Creates a GenericScopedTryLock. | |||
| As soon as it is created, this will attempt to acquire the lock, and when the | |||
| GenericScopedTryLock is deleted, the lock will be released (if the lock was | |||
| successfully acquired). | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedTryLock (const LockType& lock) throw() | |||
| : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} | |||
| /** Destructor. | |||
| The mutex will be unlocked (if it had been successfully locked) when the | |||
| destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } | |||
| /** Returns true if the mutex was successfully locked. */ | |||
| bool isLocked() const throw() { return lockWasSuccessful; } | |||
| private: | |||
| const LockType& lock_; | |||
| const bool lockWasSuccessful; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedTryLock); | |||
| }; | |||
| #endif // __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ScopedLock.h ***/ | |||
| /** | |||
| A mutex class. | |||
| @@ -6466,7 +6666,7 @@ public: | |||
| 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. | |||
| @see ScopedLock, SpinLock, Thread, InterProcessLock | |||
| @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock | |||
| */ | |||
| class JUCE_API CriticalSection | |||
| { | |||
| @@ -6485,8 +6685,9 @@ public: | |||
| 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. | |||
| Remember that it's highly recommended that you never use this method, but use a ScopedLock | |||
| to manage the locking instead. | |||
| 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 | |||
| */ | |||
| @@ -6514,11 +6715,14 @@ public: | |||
| */ | |||
| void exit() const throw(); | |||
| /** Provides the type of scoped lock to use with this type of critical section object. */ | |||
| typedef ScopedLock ScopedLockType; | |||
| /** Provides the type of scoped lock to use with a CriticalSection. */ | |||
| typedef GenericScopedLock <CriticalSection> ScopedLockType; | |||
| /** Provides the type of scoped unlocker to use with this type of critical section object. */ | |||
| typedef ScopedUnlock ScopedUnlockType; | |||
| /** Provides the type of scoped unlocker to use with a CriticalSection. */ | |||
| typedef GenericScopedUnlock <CriticalSection> ScopedUnlockType; | |||
| /** Provides the type of scoped try-locker to use with a CriticalSection. */ | |||
| typedef GenericScopedTryLock <CriticalSection> ScopedTryLockType; | |||
| private: | |||
| @@ -6571,63 +6775,99 @@ private: | |||
| }; | |||
| /** | |||
| A simple spin-lock class that can be used as a simple, low-overhead mutex for | |||
| uncontended situations. | |||
| Automatically locks and unlocks a CriticalSection object. | |||
| Note that unlike a CriticalSection, this type of lock is not re-entrant, and may | |||
| be less efficient when used it a highly contended situation, but it's very small and | |||
| requires almost no initialisation. | |||
| It's most appropriate for simple situations where you're only going to hold the | |||
| lock for a very brief time. | |||
| Use one of these as a local variable to provide RAII-based locking of a CriticalSection. | |||
| @see CriticalSection | |||
| */ | |||
| class JUCE_API SpinLock | |||
| { | |||
| public: | |||
| inline SpinLock() throw() {} | |||
| inline ~SpinLock() throw() {} | |||
| e.g. @code | |||
| void enter() const throw(); | |||
| bool tryEnter() const throw(); | |||
| CriticalSection myCriticalSection; | |||
| inline void exit() const throw() | |||
| for (;;) | |||
| { | |||
| jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! | |||
| lock = 0; | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| /** A scoped-lock type to use with a SpinLock. */ | |||
| class ScopedLockType | |||
| { | |||
| public: | |||
| inline explicit ScopedLockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.enter(); } | |||
| inline ~ScopedLockType() throw() { lock.exit(); } | |||
| @see CriticalSection, ScopedUnlock | |||
| */ | |||
| typedef CriticalSection::ScopedLockType ScopedLock; | |||
| private: | |||
| /** | |||
| Automatically unlocks and re-locks a CriticalSection object. | |||
| const SpinLock& lock; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedLockType); | |||
| }; | |||
| This is the reverse of a ScopedLock object - instead of locking the critical | |||
| section for the lifetime of this object, it unlocks it. | |||
| /** A scoped-unlocker type to use with a SpinLock. */ | |||
| class ScopedUnlockType | |||
| Make sure you don't try to unlock critical sections that aren't actually locked! | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| public: | |||
| inline explicit ScopedUnlockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.exit(); } | |||
| inline ~ScopedUnlockType() throw() { lock.enter(); } | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| private: | |||
| ... do some stuff with it locked .. | |||
| const SpinLock& lock; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedUnlockType); | |||
| }; | |||
| while (xyz) | |||
| { | |||
| ... do some stuff with it locked .. | |||
| private: | |||
| const ScopedUnlock unlocker (myCriticalSection); | |||
| mutable Atomic<int> lock; | |||
| JUCE_DECLARE_NON_COPYABLE (SpinLock); | |||
| }; | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| ...do some stuff with it unlocked ... | |||
| } | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedLock | |||
| */ | |||
| typedef CriticalSection::ScopedUnlockType ScopedUnlock; | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedTryLock myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock | |||
| */ | |||
| typedef CriticalSection::ScopedTryLockType ScopedTryLock; | |||
| #endif // __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| /*** End of inlined file: juce_CriticalSection.h ***/ | |||
| @@ -17507,137 +17747,6 @@ private: | |||
| #ifndef __JUCE_SINGLETON_JUCEHEADER__ | |||
| #define __JUCE_SINGLETON_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_ScopedLock.h ***/ | |||
| #ifndef __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| #define __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| /** | |||
| Automatically locks and unlocks a CriticalSection object. | |||
| Use one of these as a local variable to control access to a CriticalSection. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedUnlock | |||
| */ | |||
| class ScopedLock | |||
| { | |||
| public: | |||
| /** Creates a ScopedLock. | |||
| As soon as it is created, this will lock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| be unlocked. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedLock (const CriticalSection& lock) throw() : lock_ (lock) { lock.enter(); } | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedLock() throw() { lock_.exit(); } | |||
| private: | |||
| const CriticalSection& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedLock); | |||
| }; | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ... do some stuff with it locked .. | |||
| while (xyz) | |||
| { | |||
| ... do some stuff with it locked .. | |||
| const ScopedUnlock unlocker (myCriticalSection); | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| ...do some stuff with it unlocked ... | |||
| } | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedLock | |||
| */ | |||
| class ScopedUnlock | |||
| { | |||
| public: | |||
| /** Creates a ScopedUnlock. | |||
| As soon as it is created, this will unlock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| be re-locked. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedUnlock (const CriticalSection& lock) throw() : lock_ (lock) { lock.exit(); } | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedUnlock() throw() { lock_.enter(); } | |||
| private: | |||
| const CriticalSection& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedUnlock); | |||
| }; | |||
| #endif // __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ScopedLock.h ***/ | |||
| /** | |||
| Macro to declare member variables and methods for a singleton class. | |||
| @@ -21897,6 +22006,66 @@ private: | |||
| #define __JUCE_READWRITELOCK_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_SpinLock.h ***/ | |||
| #ifndef __JUCE_SPINLOCK_JUCEHEADER__ | |||
| #define __JUCE_SPINLOCK_JUCEHEADER__ | |||
| /** | |||
| A simple spin-lock class that can be used as a simple, low-overhead mutex for | |||
| uncontended situations. | |||
| Note that unlike a CriticalSection, this type of lock is not re-entrant, and may | |||
| be less efficient when used it a highly contended situation, but it's very small and | |||
| requires almost no initialisation. | |||
| It's most appropriate for simple situations where you're only going to hold the | |||
| lock for a very brief time. | |||
| @see CriticalSection | |||
| */ | |||
| class JUCE_API SpinLock | |||
| { | |||
| public: | |||
| inline SpinLock() throw() {} | |||
| inline ~SpinLock() throw() {} | |||
| /** Acquires the lock. | |||
| This will block until the lock has been successfully acquired by this thread. | |||
| Note that a SpinLock is NOT re-entrant, and is not smart enough to know whether the | |||
| caller thread already has the lock - so if a thread tries to acquire a lock that it | |||
| already holds, this method will never return! | |||
| It's strongly recommended that you never call this method directly - instead use the | |||
| ScopedLockType class to manage the locking using an RAII pattern instead. | |||
| */ | |||
| void enter() const throw(); | |||
| /** Attempts to acquire the lock, returning true if this was successful. */ | |||
| bool tryEnter() const throw(); | |||
| /** Releases the lock. */ | |||
| inline void exit() const throw() | |||
| { | |||
| jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! | |||
| lock = 0; | |||
| } | |||
| /** Provides the type of scoped lock to use for locking a SpinLock. */ | |||
| typedef GenericScopedLock <SpinLock> ScopedLockType; | |||
| /** Provides the type of scoped unlocker to use with a SpinLock. */ | |||
| typedef GenericScopedUnlock <SpinLock> ScopedUnlockType; | |||
| private: | |||
| mutable Atomic<int> lock; | |||
| JUCE_DECLARE_NON_COPYABLE (SpinLock); | |||
| }; | |||
| #endif // __JUCE_SPINLOCK_JUCEHEADER__ | |||
| /*** End of inlined file: juce_SpinLock.h ***/ | |||
| /*** Start of inlined file: juce_WaitableEvent.h ***/ | |||
| #ifndef __JUCE_WAITABLEEVENT_JUCEHEADER__ | |||
| #define __JUCE_WAITABLEEVENT_JUCEHEADER__ | |||
| @@ -22401,84 +22570,6 @@ private: | |||
| /*** End of inlined file: juce_ScopedReadLock.h ***/ | |||
| #endif | |||
| #ifndef __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| /*** Start of inlined file: juce_ScopedTryLock.h ***/ | |||
| #ifndef __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| #define __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedTryLock myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock | |||
| */ | |||
| class JUCE_API ScopedTryLock | |||
| { | |||
| public: | |||
| /** Creates a ScopedTryLock. | |||
| As soon as it is created, this will try to lock the CriticalSection, and | |||
| when the ScopedTryLock object is deleted, the CriticalSection will | |||
| be unlocked if the lock was successful. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedTryLock (const CriticalSection& lock) throw() : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked (if locked) when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } | |||
| /** Returns true if the CriticalSection was successfully locked. */ | |||
| bool isLocked() const throw() { return lockWasSuccessful; } | |||
| private: | |||
| const CriticalSection& lock_; | |||
| const bool lockWasSuccessful; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedTryLock); | |||
| }; | |||
| #endif // __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ScopedTryLock.h ***/ | |||
| #endif | |||
| #ifndef __JUCE_SCOPEDWRITELOCK_JUCEHEADER__ | |||
| @@ -22544,6 +22635,9 @@ private: | |||
| /*** End of inlined file: juce_ScopedWriteLock.h ***/ | |||
| #endif | |||
| #ifndef __JUCE_SPINLOCK_JUCEHEADER__ | |||
| #endif | |||
| #ifndef __JUCE_THREAD_JUCEHEADER__ | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioFormatReaderSource.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioSourcePlayer.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioTransportSource.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../memory/juce_ScopedPointer.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_BufferingAudioSource.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../core/juce_Singleton.h" | |||
| #include "../../containers/juce_Array.h" | |||
| #include "../../utilities/juce_DeletedAtShutdown.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ChannelRemappingAudioSource.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MixerAudioSource.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../containers/juce_OwnedArray.h" | |||
| @@ -27,7 +27,7 @@ | |||
| #define __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__ | |||
| #include "juce_AudioSource.h" | |||
| #include "../../threads/juce_CriticalSection.h" | |||
| #include "../../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_IIRFilter.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -27,7 +27,6 @@ | |||
| #define __JUCE_MIDIKEYBOARDSTATE_JUCEHEADER__ | |||
| #include "juce_MidiBuffer.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../containers/juce_Array.h" | |||
| class MidiKeyboardState; | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MidiMessageCollector.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../core/juce_Time.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_MidiOutput.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../core/juce_Time.h" | |||
| @@ -43,7 +43,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioUnitPluginFormat.h" | |||
| #include "../juce_PluginDescription.h" | |||
| #include "../../../threads/juce_ScopedLock.h" | |||
| #include "../../../threads/juce_CriticalSection.h" | |||
| #include "../../../events/juce_Timer.h" | |||
| #include "../../../core/juce_PlatformUtilities.h" | |||
| #include "../../../gui/components/layout/juce_ComponentMovementWatcher.h" | |||
| @@ -63,7 +63,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_VSTPluginFormat.h" | |||
| #include "../../../threads/juce_Process.h" | |||
| #include "../../../threads/juce_ScopedLock.h" | |||
| #include "../../../threads/juce_CriticalSection.h" | |||
| #include "../../../maths/juce_Random.h" | |||
| #include "../../../io/files/juce_DirectoryIterator.h" | |||
| #include "../../../events/juce_Timer.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioProcessor.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../text/juce_XmlDocument.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_AudioProcessorPlayer.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_Synthesiser.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_PropertySet.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../text/juce_XmlDocument.h" | |||
| @@ -30,7 +30,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_FileLogger.h" | |||
| #include "../io/files/juce_FileOutputStream.h" | |||
| #include "../io/files/juce_FileInputStream.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../memory/juce_ScopedPointer.h" | |||
| #include "juce_SystemStats.h" | |||
| @@ -26,8 +26,6 @@ | |||
| #ifndef __JUCE_SINGLETON_JUCEHEADER__ | |||
| #define __JUCE_SINGLETON_JUCEHEADER__ | |||
| #include "../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| /** | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 53 | |||
| #define JUCE_BUILDNUMBER 63 | |||
| #define JUCE_BUILDNUMBER 64 | |||
| /** Current Juce version number. | |||
| @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ActionBroadcaster.h" | |||
| #include "juce_MessageManager.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_InterprocessConnection.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../memory/juce_ScopedPointer.h" | |||
| @@ -32,7 +32,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../application/juce_Application.h" | |||
| #include "../gui/components/juce_Component.h" | |||
| #include "../threads/juce_Thread.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../core/juce_Time.h" | |||
| //============================================================================== | |||
| @@ -28,6 +28,7 @@ | |||
| #include "juce_Timer.h" | |||
| #include "../containers/juce_OwnedArray.h" | |||
| #include "../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -34,7 +34,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../utilities/juce_DeletedAtShutdown.h" | |||
| #include "../core/juce_Time.h" | |||
| #include "../threads/juce_Thread.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_DirectoryContentsList.h" | |||
| #include "../../graphics/imaging/juce_ImageCache.h" | |||
| #include "../../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -31,6 +31,7 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../juce_Component.h" | |||
| #include "../lookandfeel/juce_LookAndFeel.h" | |||
| #include "../mouse/juce_MouseInputSource.h" | |||
| #include "../../../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -32,7 +32,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_OpenGLComponent.h" | |||
| #include "../windows/juce_ComponentPeer.h" | |||
| #include "../layout/juce_ComponentMovementWatcher.h" | |||
| #include "../../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ImageCache.h" | |||
| #include "juce_ImageFileFormat.h" | |||
| #include "../../../threads/juce_ScopedLock.h" | |||
| #include "../../../utilities/juce_DeletedAtShutdown.h" | |||
| #include "../../../containers/juce_OwnedArray.h" | |||
| #include "../../../events/juce_Timer.h" | |||
| @@ -35,7 +35,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../streams/juce_GZIPCompressorOutputStream.h" | |||
| #include "juce_FileInputStream.h" | |||
| #include "juce_FileOutputStream.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -58,7 +58,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_Socket.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../threads/juce_Thread.h" | |||
| #if JUCE_WINDOWS | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_OutputStream.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../containers/juce_Array.h" | |||
| #include "../../memory/juce_ScopedPointer.h" | |||
| #include "../files/juce_FileInputStream.h" | |||
| @@ -296,12 +296,12 @@ | |||
| #ifndef __JUCE_SCOPEDREADLOCK_JUCEHEADER__ | |||
| #include "threads/juce_ScopedReadLock.h" | |||
| #endif | |||
| #ifndef __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| #include "threads/juce_ScopedTryLock.h" | |||
| #endif | |||
| #ifndef __JUCE_SCOPEDWRITELOCK_JUCEHEADER__ | |||
| #include "threads/juce_ScopedWriteLock.h" | |||
| #endif | |||
| #ifndef __JUCE_SPINLOCK_JUCEHEADER__ | |||
| #include "threads/juce_SpinLock.h" | |||
| #endif | |||
| #ifndef __JUCE_THREAD_JUCEHEADER__ | |||
| #include "threads/juce_Thread.h" | |||
| #endif | |||
| @@ -56,7 +56,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../../text/juce_XmlDocument.h" | |||
| #include "../../threads/juce_CriticalSection.h" | |||
| #include "../../threads/juce_Thread.h" | |||
| #include "../../threads/juce_ScopedLock.h" | |||
| #include "../../threads/juce_InterProcessLock.h" | |||
| #include "../../threads/juce_WaitableEvent.h" | |||
| #include "../../threads/juce_Process.h" | |||
| @@ -29,10 +29,7 @@ | |||
| //============================================================================== | |||
| static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| NEWTEXTMETRICEXW*, | |||
| int type, | |||
| LPARAM lParam) | |||
| static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| @@ -44,10 +41,7 @@ static int CALLBACK wfontEnum2 (ENUMLOGFONTEXW* lpelfe, | |||
| return 1; | |||
| } | |||
| static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| NEWTEXTMETRICEXW*, | |||
| int type, | |||
| LPARAM lParam) | |||
| static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, NEWTEXTMETRICEXW*, int type, LPARAM lParam) | |||
| { | |||
| if (lpelfe != 0 && (type & RASTER_FONTTYPE) == 0) | |||
| { | |||
| @@ -60,7 +54,7 @@ static int CALLBACK wfontEnum1 (ENUMLOGFONTEXW* lpelfe, | |||
| lf.lfPitchAndFamily = FF_DONTCARE; | |||
| const String fontName (lpelfe->elfLogFont.lfFaceName); | |||
| fontName.copyToUTF16 (lf.lfFaceName, LF_FACESIZE - 1); | |||
| fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); | |||
| HDC dc = CreateCompatibleDC (0); | |||
| EnumFontFamiliesEx (dc, &lf, | |||
| @@ -85,7 +79,6 @@ const StringArray Font::findAllTypefaceNames() | |||
| lf.lfCharSet = DEFAULT_CHARSET; | |||
| lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lf.lfPitchAndFamily = FF_DONTCARE; | |||
| lf.lfFaceName[0] = 0; | |||
| EnumFontFamiliesEx (dc, &lf, | |||
| (FONTENUMPROCW) &wfontEnum1, | |||
| @@ -154,18 +147,18 @@ public: | |||
| SetMapperFlags (dc, 0); | |||
| SetMapMode (dc, MM_TEXT); | |||
| LOGFONTW lfw = { 0 }; | |||
| lfw.lfCharSet = DEFAULT_CHARSET; | |||
| lfw.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lfw.lfOutPrecision = OUT_OUTLINE_PRECIS; | |||
| lfw.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |||
| lfw.lfQuality = PROOF_QUALITY; | |||
| lfw.lfItalic = (BYTE) (italic ? TRUE : FALSE); | |||
| lfw.lfWeight = bold ? FW_BOLD : FW_NORMAL; | |||
| fontName.copyToUTF16 (lfw.lfFaceName, LF_FACESIZE - 1); | |||
| LOGFONTW lf = { 0 }; | |||
| lf.lfCharSet = DEFAULT_CHARSET; | |||
| lf.lfClipPrecision = CLIP_DEFAULT_PRECIS; | |||
| lf.lfOutPrecision = OUT_OUTLINE_PRECIS; | |||
| lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; | |||
| lf.lfQuality = PROOF_QUALITY; | |||
| lf.lfItalic = (BYTE) (italic ? TRUE : FALSE); | |||
| lf.lfWeight = bold ? FW_BOLD : FW_NORMAL; | |||
| lf.lfHeight = size > 0 ? size : -256; | |||
| fontName.copyToUTF16 (lf.lfFaceName, sizeof (lf.lfFaceName)); | |||
| lfw.lfHeight = size > 0 ? size : -256; | |||
| HFONT standardSizedFont = CreateFontIndirect (&lfw); | |||
| HFONT standardSizedFont = CreateFontIndirect (&lf); | |||
| if (standardSizedFont != 0) | |||
| { | |||
| @@ -178,8 +171,8 @@ public: | |||
| OUTLINETEXTMETRIC otm; | |||
| if (GetOutlineTextMetrics (dc, sizeof (otm), &otm) != 0) | |||
| { | |||
| lfw.lfHeight = -(int) otm.otmEMSquare; | |||
| fontH = CreateFontIndirect (&lfw); | |||
| lf.lfHeight = -(int) otm.otmEMSquare; | |||
| fontH = CreateFontIndirect (&lf); | |||
| SelectObject (dc, fontH); | |||
| DeleteObject (standardSizedFont); | |||
| @@ -28,6 +28,7 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_LocalisedStrings.h" | |||
| #include "../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -26,10 +26,7 @@ | |||
| #ifndef __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| #define __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| #ifndef DOXYGEN | |||
| class ScopedLock; | |||
| class ScopedUnlock; | |||
| #endif | |||
| #include "juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -40,7 +37,7 @@ | |||
| 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. | |||
| @see ScopedLock, SpinLock, Thread, InterProcessLock | |||
| @see ScopedLock, ScopedTryLock, ScopedUnlock, SpinLock, ReadWriteLock, Thread, InterProcessLock | |||
| */ | |||
| class JUCE_API CriticalSection | |||
| { | |||
| @@ -60,8 +57,9 @@ public: | |||
| 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. | |||
| Remember that it's highly recommended that you never use this method, but use a ScopedLock | |||
| to manage the locking instead. | |||
| 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 | |||
| */ | |||
| @@ -91,11 +89,14 @@ public: | |||
| //============================================================================== | |||
| /** Provides the type of scoped lock to use with this type of critical section object. */ | |||
| typedef ScopedLock ScopedLockType; | |||
| /** Provides the type of scoped lock to use with a CriticalSection. */ | |||
| typedef GenericScopedLock <CriticalSection> ScopedLockType; | |||
| /** Provides the type of scoped unlocker to use with a CriticalSection. */ | |||
| typedef GenericScopedUnlock <CriticalSection> ScopedUnlockType; | |||
| /** Provides the type of scoped unlocker to use with this type of critical section object. */ | |||
| typedef ScopedUnlock ScopedUnlockType; | |||
| /** Provides the type of scoped try-locker to use with a CriticalSection. */ | |||
| typedef GenericScopedTryLock <CriticalSection> ScopedTryLockType; | |||
| private: | |||
| @@ -151,68 +152,103 @@ private: | |||
| JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection); | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| A simple spin-lock class that can be used as a simple, low-overhead mutex for | |||
| uncontended situations. | |||
| Automatically locks and unlocks a CriticalSection object. | |||
| Note that unlike a CriticalSection, this type of lock is not re-entrant, and may | |||
| be less efficient when used it a highly contended situation, but it's very small and | |||
| requires almost no initialisation. | |||
| It's most appropriate for simple situations where you're only going to hold the | |||
| lock for a very brief time. | |||
| Use one of these as a local variable to provide RAII-based locking of a CriticalSection. | |||
| @see CriticalSection | |||
| */ | |||
| class JUCE_API SpinLock | |||
| { | |||
| public: | |||
| inline SpinLock() throw() {} | |||
| inline ~SpinLock() throw() {} | |||
| e.g. @code | |||
| void enter() const throw(); | |||
| bool tryEnter() const throw(); | |||
| CriticalSection myCriticalSection; | |||
| inline void exit() const throw() | |||
| for (;;) | |||
| { | |||
| jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! | |||
| lock = 0; | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| //============================================================================== | |||
| /** A scoped-lock type to use with a SpinLock. */ | |||
| class ScopedLockType | |||
| @see CriticalSection, ScopedUnlock | |||
| */ | |||
| typedef CriticalSection::ScopedLockType ScopedLock; | |||
| //============================================================================== | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| public: | |||
| inline explicit ScopedLockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.enter(); } | |||
| inline ~ScopedLockType() throw() { lock.exit(); } | |||
| private: | |||
| //============================================================================== | |||
| const SpinLock& lock; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedLockType); | |||
| }; | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| //============================================================================== | |||
| /** A scoped-unlocker type to use with a SpinLock. */ | |||
| class ScopedUnlockType | |||
| ... do some stuff with it locked .. | |||
| while (xyz) | |||
| { | |||
| ... do some stuff with it locked .. | |||
| const ScopedUnlock unlocker (myCriticalSection); | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| ...do some stuff with it unlocked ... | |||
| } | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedLock | |||
| */ | |||
| typedef CriticalSection::ScopedUnlockType ScopedUnlock; | |||
| //============================================================================== | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| public: | |||
| inline explicit ScopedUnlockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.exit(); } | |||
| inline ~ScopedUnlockType() throw() { lock.enter(); } | |||
| private: | |||
| //============================================================================== | |||
| const SpinLock& lock; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedUnlockType); | |||
| }; | |||
| const ScopedTryLock myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| private: | |||
| //============================================================================== | |||
| mutable Atomic<int> lock; | |||
| JUCE_DECLARE_NON_COPYABLE (SpinLock); | |||
| }; | |||
| @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock | |||
| */ | |||
| typedef CriticalSection::ScopedTryLockType ScopedTryLock; | |||
| #endif // __JUCE_CRITICALSECTION_JUCEHEADER__ | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_ReadWriteLock.h" | |||
| #include "juce_ScopedLock.h" | |||
| #include "juce_Thread.h" | |||
| @@ -27,6 +27,7 @@ | |||
| #define __JUCE_READWRITELOCK_JUCEHEADER__ | |||
| #include "juce_CriticalSection.h" | |||
| #include "juce_SpinLock.h" | |||
| #include "juce_WaitableEvent.h" | |||
| #include "juce_Thread.h" | |||
| #include "../containers/juce_Array.h" | |||
| @@ -26,22 +26,22 @@ | |||
| #ifndef __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| #define __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| #include "juce_CriticalSection.h" | |||
| //============================================================================== | |||
| /** | |||
| Automatically locks and unlocks a CriticalSection object. | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to control access to a CriticalSection. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| e.g. @code | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| @@ -50,50 +50,47 @@ | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedUnlock | |||
| @see GenericScopedUnlock, CriticalSection, SpinLock, ScopedLock, ScopedUnlock | |||
| */ | |||
| class ScopedLock | |||
| template <class LockType> | |||
| class GenericScopedLock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a ScopedLock. | |||
| /** Creates a GenericScopedLock. | |||
| As soon as it is created, this will lock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| be unlocked. | |||
| As soon as it is created, this will acquire the lock, and when the GenericScopedLock | |||
| object is deleted, the lock will be released. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedLock (const CriticalSection& lock) throw() : lock_ (lock) { lock.enter(); } | |||
| inline explicit GenericScopedLock (const LockType& lock) throw() : lock_ (lock) { lock.enter(); } | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| The lock will be released when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, otherwise there are | |||
| no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedLock() throw() { lock_.exit(); } | |||
| inline ~GenericScopedLock() throw() { lock_.exit(); } | |||
| private: | |||
| //============================================================================== | |||
| const CriticalSection& lock_; | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedLock); | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedLock); | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| Automatically unlocks and re-locks a CriticalSection object. | |||
| Automatically unlocks and re-locks a mutex object. | |||
| This is the reverse of a ScopedLock object - instead of locking the critical | |||
| section for the lifetime of this object, it unlocks it. | |||
| This is the reverse of a GenericScopedLock object - instead of locking the mutex | |||
| for the lifetime of this object, it unlocks it. | |||
| Make sure you don't try to unlock critical sections that aren't actually locked! | |||
| Make sure you don't try to unlock mutexes that aren't actually locked! | |||
| e.g. @code | |||
| @@ -101,7 +98,7 @@ private: | |||
| for (;;) | |||
| { | |||
| const ScopedLock myScopedLock (myCriticalSection); | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ... do some stuff with it locked .. | |||
| @@ -110,7 +107,7 @@ private: | |||
| { | |||
| ... do some stuff with it locked .. | |||
| const ScopedUnlock unlocker (myCriticalSection); | |||
| const GenericScopedUnlock<CriticalSection> unlocker (myCriticalSection); | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| @@ -122,13 +119,14 @@ private: | |||
| } | |||
| @endcode | |||
| @see CriticalSection, ScopedLock | |||
| @see GenericScopedLock, CriticalSection, ScopedLock, ScopedUnlock | |||
| */ | |||
| class ScopedUnlock | |||
| template <class LockType> | |||
| class GenericScopedUnlock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a ScopedUnlock. | |||
| /** Creates a GenericScopedUnlock. | |||
| As soon as it is created, this will unlock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| @@ -138,7 +136,7 @@ public: | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedUnlock (const CriticalSection& lock) throw() : lock_ (lock) { lock.exit(); } | |||
| inline explicit GenericScopedUnlock (const LockType& lock) throw() : lock_ (lock) { lock.exit(); } | |||
| /** Destructor. | |||
| @@ -147,16 +145,90 @@ public: | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedUnlock() throw() { lock_.enter(); } | |||
| inline ~GenericScopedUnlock() throw() { lock_.enter(); } | |||
| private: | |||
| //============================================================================== | |||
| const CriticalSection& lock_; | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedUnlock); | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedUnlock); | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedTryLock<CriticalSection> myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, GenericScopedLock, GenericScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedTryLock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a GenericScopedTryLock. | |||
| As soon as it is created, this will attempt to acquire the lock, and when the | |||
| GenericScopedTryLock is deleted, the lock will be released (if the lock was | |||
| successfully acquired). | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedTryLock (const LockType& lock) throw() | |||
| : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} | |||
| /** Destructor. | |||
| The mutex will be unlocked (if it had been successfully locked) when the | |||
| destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } | |||
| /** Returns true if the mutex was successfully locked. */ | |||
| bool isLocked() const throw() { return lockWasSuccessful; } | |||
| private: | |||
| //============================================================================== | |||
| const LockType& lock_; | |||
| const bool lockWasSuccessful; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedTryLock); | |||
| }; | |||
| #endif // __JUCE_SCOPEDLOCK_JUCEHEADER__ | |||
| @@ -1,101 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| #define __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| #include "juce_CriticalSection.h" | |||
| //============================================================================== | |||
| /** | |||
| 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 | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const ScopedTryLock myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock | |||
| */ | |||
| class JUCE_API ScopedTryLock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a ScopedTryLock. | |||
| As soon as it is created, this will try to lock the CriticalSection, and | |||
| when the ScopedTryLock object is deleted, the CriticalSection will | |||
| be unlocked if the lock was successful. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit ScopedTryLock (const CriticalSection& lock) throw() : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked (if locked) when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~ScopedTryLock() throw() { if (lockWasSuccessful) lock_.exit(); } | |||
| /** Returns true if the CriticalSection was successfully locked. */ | |||
| bool isLocked() const throw() { return lockWasSuccessful; } | |||
| private: | |||
| //============================================================================== | |||
| const CriticalSection& lock_; | |||
| const bool lockWasSuccessful; | |||
| JUCE_DECLARE_NON_COPYABLE (ScopedTryLock); | |||
| }; | |||
| #endif // __JUCE_SCOPEDTRYLOCK_JUCEHEADER__ | |||
| @@ -0,0 +1,87 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-11 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_SPINLOCK_JUCEHEADER__ | |||
| #define __JUCE_SPINLOCK_JUCEHEADER__ | |||
| #include "juce_ScopedLock.h" | |||
| //============================================================================== | |||
| /** | |||
| A simple spin-lock class that can be used as a simple, low-overhead mutex for | |||
| uncontended situations. | |||
| Note that unlike a CriticalSection, this type of lock is not re-entrant, and may | |||
| be less efficient when used it a highly contended situation, but it's very small and | |||
| requires almost no initialisation. | |||
| It's most appropriate for simple situations where you're only going to hold the | |||
| lock for a very brief time. | |||
| @see CriticalSection | |||
| */ | |||
| class JUCE_API SpinLock | |||
| { | |||
| public: | |||
| inline SpinLock() throw() {} | |||
| inline ~SpinLock() throw() {} | |||
| /** Acquires the lock. | |||
| This will block until the lock has been successfully acquired by this thread. | |||
| Note that a SpinLock is NOT re-entrant, and is not smart enough to know whether the | |||
| caller thread already has the lock - so if a thread tries to acquire a lock that it | |||
| already holds, this method will never return! | |||
| It's strongly recommended that you never call this method directly - instead use the | |||
| ScopedLockType class to manage the locking using an RAII pattern instead. | |||
| */ | |||
| void enter() const throw(); | |||
| /** Attempts to acquire the lock, returning true if this was successful. */ | |||
| bool tryEnter() const throw(); | |||
| /** Releases the lock. */ | |||
| inline void exit() const throw() | |||
| { | |||
| jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! | |||
| lock = 0; | |||
| } | |||
| //============================================================================== | |||
| /** Provides the type of scoped lock to use for locking a SpinLock. */ | |||
| typedef GenericScopedLock <SpinLock> ScopedLockType; | |||
| /** Provides the type of scoped unlocker to use with a SpinLock. */ | |||
| typedef GenericScopedUnlock <SpinLock> ScopedUnlockType; | |||
| private: | |||
| //============================================================================== | |||
| mutable Atomic<int> lock; | |||
| JUCE_DECLARE_NON_COPYABLE (SpinLock); | |||
| }; | |||
| #endif // __JUCE_SPINLOCK_JUCEHEADER__ | |||
| @@ -28,7 +28,7 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_Thread.h" | |||
| #include "juce_ScopedLock.h" | |||
| #include "juce_SpinLock.h" | |||
| #include "../core/juce_Time.h" | |||
| @@ -27,7 +27,6 @@ | |||
| #define __JUCE_THREADPOOL_JUCEHEADER__ | |||
| #include "juce_Thread.h" | |||
| #include "juce_ScopedLock.h" | |||
| #include "../text/juce_StringArray.h" | |||
| #include "../containers/juce_Array.h" | |||
| #include "../containers/juce_OwnedArray.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_TimeSliceThread.h" | |||
| #include "juce_ScopedLock.h" | |||
| //============================================================================== | |||
| @@ -29,8 +29,8 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "juce_DeletedAtShutdown.h" | |||
| #include "../containers/juce_Array.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../application/juce_Application.h" | |||
| #include "../threads/juce_SpinLock.h" | |||
| //============================================================================== | |||
| @@ -38,7 +38,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../memory/juce_ScopedPointer.h" | |||
| #include "../core/juce_SystemStats.h" | |||
| #include "../threads/juce_InterProcessLock.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| #include "../text/juce_XmlDocument.h" | |||
| @@ -28,7 +28,6 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_UnitTest.h" | |||
| #include "../threads/juce_ScopedLock.h" | |||
| //============================================================================== | |||