From fa04e0cf93f08c52f95d95cf46538a9a905ea4f5 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Thu, 31 Mar 2011 11:21:49 +0100 Subject: [PATCH] win32 font name length fix. Tidied up ScopedLock class structure, creating some templated classes for generic RAII locking. --- Builds/MacOSX/Juce.xcodeproj/project.pbxproj | 4 +- Builds/VisualStudio2005/Juce.vcproj | 2 +- Builds/VisualStudio2008/Juce.vcproj | 2 +- Builds/VisualStudio2008_DLL/Juce.vcproj | 2 +- Builds/VisualStudio2010/Juce.vcxproj | 2 +- Builds/VisualStudio2010/Juce.vcxproj.filters | 4 +- Builds/iOS/Juce.xcodeproj/project.pbxproj | 4 +- Juce.jucer | 3 +- juce_amalgamated.cpp | 39 +- juce_amalgamated.h | 620 ++++++++++-------- .../juce_AudioFormatReaderSource.cpp | 1 - .../audio_sources/juce_AudioSourcePlayer.cpp | 1 - .../juce_AudioTransportSource.cpp | 1 - .../juce_BufferingAudioSource.cpp | 1 - .../juce_ChannelRemappingAudioSource.cpp | 1 - .../audio_sources/juce_MixerAudioSource.cpp | 1 - .../juce_ResamplingAudioSource.h | 2 +- src/audio/dsp/juce_IIRFilter.cpp | 1 - src/audio/midi/juce_MidiKeyboardState.h | 1 - src/audio/midi/juce_MidiMessageCollector.cpp | 1 - src/audio/midi/juce_MidiOutput.cpp | 1 - .../formats/juce_AudioUnitPluginFormat.mm | 2 +- .../plugins/formats/juce_VSTPluginFormat.cpp | 2 +- src/audio/processors/juce_AudioProcessor.cpp | 1 - .../processors/juce_AudioProcessorPlayer.cpp | 1 - src/audio/synthesisers/juce_Synthesiser.cpp | 1 - src/containers/juce_PropertySet.cpp | 1 - src/core/juce_FileLogger.cpp | 1 - src/core/juce_Singleton.h | 2 - src/core/juce_StandardHeader.h | 2 +- src/events/juce_ActionBroadcaster.cpp | 1 - src/events/juce_InterprocessConnection.cpp | 1 - src/events/juce_MessageManager.cpp | 1 - src/events/juce_MultiTimer.h | 1 + src/events/juce_Timer.cpp | 2 +- .../juce_DirectoryContentsList.cpp | 1 - src/gui/components/mouse/juce_MouseCursor.cpp | 1 + .../special/juce_OpenGLComponent.cpp | 1 - src/gui/graphics/imaging/juce_ImageCache.cpp | 1 - src/io/files/juce_ZipFile.cpp | 1 - src/io/network/juce_Socket.cpp | 1 - src/io/streams/juce_OutputStream.cpp | 1 - src/juce_core_includes.h | 6 +- src/native/linux/juce_linux_NativeCode.cpp | 1 - src/native/windows/juce_win32_Fonts.cpp | 39 +- src/text/juce_LocalisedStrings.cpp | 1 + src/threads/juce_CriticalSection.h | 154 +++-- src/threads/juce_ReadWriteLock.cpp | 1 - src/threads/juce_ReadWriteLock.h | 1 + src/threads/juce_ScopedLock.h | 142 +++- src/threads/juce_ScopedTryLock.h | 101 --- src/threads/juce_SpinLock.h | 87 +++ src/threads/juce_Thread.cpp | 2 +- src/threads/juce_ThreadPool.h | 1 - src/threads/juce_TimeSliceThread.cpp | 1 - src/utilities/juce_DeletedAtShutdown.cpp | 2 +- src/utilities/juce_PropertiesFile.cpp | 1 - src/utilities/juce_UnitTest.cpp | 1 - 58 files changed, 703 insertions(+), 558 deletions(-) delete mode 100644 src/threads/juce_ScopedTryLock.h create mode 100644 src/threads/juce_SpinLock.h diff --git a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj index 6454152384..580787090d 100644 --- a/Builds/MacOSX/Juce.xcodeproj/project.pbxproj +++ b/Builds/MacOSX/Juce.xcodeproj/project.pbxproj @@ -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, diff --git a/Builds/VisualStudio2005/Juce.vcproj b/Builds/VisualStudio2005/Juce.vcproj index a700feef71..d121f0c26d 100644 --- a/Builds/VisualStudio2005/Juce.vcproj +++ b/Builds/VisualStudio2005/Juce.vcproj @@ -993,8 +993,8 @@ - + diff --git a/Builds/VisualStudio2008/Juce.vcproj b/Builds/VisualStudio2008/Juce.vcproj index 5b9ecf6a92..47e691bedf 100644 --- a/Builds/VisualStudio2008/Juce.vcproj +++ b/Builds/VisualStudio2008/Juce.vcproj @@ -993,8 +993,8 @@ - + diff --git a/Builds/VisualStudio2008_DLL/Juce.vcproj b/Builds/VisualStudio2008_DLL/Juce.vcproj index 0767d2efa9..548f7375a4 100644 --- a/Builds/VisualStudio2008_DLL/Juce.vcproj +++ b/Builds/VisualStudio2008_DLL/Juce.vcproj @@ -995,8 +995,8 @@ - + diff --git a/Builds/VisualStudio2010/Juce.vcxproj b/Builds/VisualStudio2010/Juce.vcxproj index da52c95bae..0e2bc2c2df 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj +++ b/Builds/VisualStudio2010/Juce.vcxproj @@ -800,8 +800,8 @@ - + diff --git a/Builds/VisualStudio2010/Juce.vcxproj.filters b/Builds/VisualStudio2010/Juce.vcxproj.filters index 51f271e6fe..e09cdb63dd 100644 --- a/Builds/VisualStudio2010/Juce.vcxproj.filters +++ b/Builds/VisualStudio2010/Juce.vcxproj.filters @@ -2334,10 +2334,10 @@ Juce\Source\threads - + Juce\Source\threads - + Juce\Source\threads diff --git a/Builds/iOS/Juce.xcodeproj/project.pbxproj b/Builds/iOS/Juce.xcodeproj/project.pbxproj index 424c0b75d0..c8dad8c8bf 100644 --- a/Builds/iOS/Juce.xcodeproj/project.pbxproj +++ b/Builds/iOS/Juce.xcodeproj/project.pbxproj @@ -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, diff --git a/Juce.jucer b/Juce.jucer index 849df70a53..1072c3c8d7 100644 --- a/Juce.jucer +++ b/Juce.jucer @@ -1541,10 +1541,9 @@ file="src/threads/juce_ScopedLock.h"/> - + 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); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 5453b7f0f3..57e4c285a7 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -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 myScopedLock (myCriticalSection); + // myCriticalSection is now locked + + ...do some stuff... + + // myCriticalSection gets unlocked here. + } + @endcode + + @see GenericScopedUnlock, CriticalSection, SpinLock, ScopedLock, ScopedUnlock +*/ +template +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 myScopedLock (myCriticalSection); + // myCriticalSection is now locked + + ... do some stuff with it locked .. + + while (xyz) + { + ... do some stuff with it locked .. + + const GenericScopedUnlock 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 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 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 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 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 ScopedUnlockType; + + /** Provides the type of scoped try-locker to use with a CriticalSection. */ + typedef GenericScopedTryLock 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 + @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(); } + const ScopedLock myScopedLock (myCriticalSection); + // myCriticalSection is now locked - private: + ... do some stuff with it locked .. - const SpinLock& lock; - JUCE_DECLARE_NON_COPYABLE (ScopedLockType); - }; + while (xyz) + { + ... do some stuff with it locked .. - /** A scoped-unlocker type to use with a SpinLock. */ - class ScopedUnlockType + 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(); } + const ScopedTryLock myScopedTryLock (myCriticalSection); - private: + // 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.. + } - const SpinLock& lock; - JUCE_DECLARE_NON_COPYABLE (ScopedUnlockType); - }; + // myCriticalSection gets unlocked here (if it was locked) + } + @endcode -private: - - mutable Atomic lock; - JUCE_DECLARE_NON_COPYABLE (SpinLock); -}; + @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 ScopedLockType; + + /** Provides the type of scoped unlocker to use with a SpinLock. */ + typedef GenericScopedUnlock ScopedUnlockType; + +private: + + mutable Atomic 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__ diff --git a/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp b/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp index c87b69b1fd..55ab959829 100644 --- a/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp +++ b/src/audio/audio_sources/juce_AudioFormatReaderSource.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioFormatReaderSource.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/audio/audio_sources/juce_AudioSourcePlayer.cpp b/src/audio/audio_sources/juce_AudioSourcePlayer.cpp index fdba8543e7..3a5e449411 100644 --- a/src/audio/audio_sources/juce_AudioSourcePlayer.cpp +++ b/src/audio/audio_sources/juce_AudioSourcePlayer.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioSourcePlayer.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/audio/audio_sources/juce_AudioTransportSource.cpp b/src/audio/audio_sources/juce_AudioTransportSource.cpp index 67afde6b5f..299603a557 100644 --- a/src/audio/audio_sources/juce_AudioTransportSource.cpp +++ b/src/audio/audio_sources/juce_AudioTransportSource.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioTransportSource.h" -#include "../../threads/juce_ScopedLock.h" #include "../../memory/juce_ScopedPointer.h" diff --git a/src/audio/audio_sources/juce_BufferingAudioSource.cpp b/src/audio/audio_sources/juce_BufferingAudioSource.cpp index 98aa43b2c0..a032d6e24c 100644 --- a/src/audio/audio_sources/juce_BufferingAudioSource.cpp +++ b/src/audio/audio_sources/juce_BufferingAudioSource.cpp @@ -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" diff --git a/src/audio/audio_sources/juce_ChannelRemappingAudioSource.cpp b/src/audio/audio_sources/juce_ChannelRemappingAudioSource.cpp index cea8d751e1..ed6e810ce6 100644 --- a/src/audio/audio_sources/juce_ChannelRemappingAudioSource.cpp +++ b/src/audio/audio_sources/juce_ChannelRemappingAudioSource.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_ChannelRemappingAudioSource.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/audio/audio_sources/juce_MixerAudioSource.cpp b/src/audio/audio_sources/juce_MixerAudioSource.cpp index 46970fe806..30aa710c08 100644 --- a/src/audio/audio_sources/juce_MixerAudioSource.cpp +++ b/src/audio/audio_sources/juce_MixerAudioSource.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_MixerAudioSource.h" -#include "../../threads/juce_ScopedLock.h" #include "../../containers/juce_OwnedArray.h" diff --git a/src/audio/audio_sources/juce_ResamplingAudioSource.h b/src/audio/audio_sources/juce_ResamplingAudioSource.h index b6b9902900..0dcccb562d 100644 --- a/src/audio/audio_sources/juce_ResamplingAudioSource.h +++ b/src/audio/audio_sources/juce_ResamplingAudioSource.h @@ -27,7 +27,7 @@ #define __JUCE_RESAMPLINGAUDIOSOURCE_JUCEHEADER__ #include "juce_AudioSource.h" -#include "../../threads/juce_CriticalSection.h" +#include "../../threads/juce_SpinLock.h" //============================================================================== diff --git a/src/audio/dsp/juce_IIRFilter.cpp b/src/audio/dsp/juce_IIRFilter.cpp index ed228107c0..421d60752e 100644 --- a/src/audio/dsp/juce_IIRFilter.cpp +++ b/src/audio/dsp/juce_IIRFilter.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_IIRFilter.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/audio/midi/juce_MidiKeyboardState.h b/src/audio/midi/juce_MidiKeyboardState.h index a44aab8858..e774e6ccbe 100644 --- a/src/audio/midi/juce_MidiKeyboardState.h +++ b/src/audio/midi/juce_MidiKeyboardState.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; diff --git a/src/audio/midi/juce_MidiMessageCollector.cpp b/src/audio/midi/juce_MidiMessageCollector.cpp index 0b64d97f99..e9c66aba55 100644 --- a/src/audio/midi/juce_MidiMessageCollector.cpp +++ b/src/audio/midi/juce_MidiMessageCollector.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_MidiMessageCollector.h" -#include "../../threads/juce_ScopedLock.h" #include "../../core/juce_Time.h" diff --git a/src/audio/midi/juce_MidiOutput.cpp b/src/audio/midi/juce_MidiOutput.cpp index 78ad380074..1b21c93c91 100644 --- a/src/audio/midi/juce_MidiOutput.cpp +++ b/src/audio/midi/juce_MidiOutput.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_MidiOutput.h" -#include "../../threads/juce_ScopedLock.h" #include "../../core/juce_Time.h" diff --git a/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm b/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm index 3071a919d0..8cb56aac8f 100644 --- a/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm +++ b/src/audio/plugins/formats/juce_AudioUnitPluginFormat.mm @@ -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" diff --git a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp index 3570487aa9..ede368a907 100644 --- a/src/audio/plugins/formats/juce_VSTPluginFormat.cpp +++ b/src/audio/plugins/formats/juce_VSTPluginFormat.cpp @@ -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" diff --git a/src/audio/processors/juce_AudioProcessor.cpp b/src/audio/processors/juce_AudioProcessor.cpp index 25535861e9..9ee74939a3 100644 --- a/src/audio/processors/juce_AudioProcessor.cpp +++ b/src/audio/processors/juce_AudioProcessor.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioProcessor.h" -#include "../../threads/juce_ScopedLock.h" #include "../../text/juce_XmlDocument.h" diff --git a/src/audio/processors/juce_AudioProcessorPlayer.cpp b/src/audio/processors/juce_AudioProcessorPlayer.cpp index 1b159a86fc..ebe21757cf 100644 --- a/src/audio/processors/juce_AudioProcessorPlayer.cpp +++ b/src/audio/processors/juce_AudioProcessorPlayer.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AudioProcessorPlayer.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/audio/synthesisers/juce_Synthesiser.cpp b/src/audio/synthesisers/juce_Synthesiser.cpp index 63312bd990..66746be2cf 100644 --- a/src/audio/synthesisers/juce_Synthesiser.cpp +++ b/src/audio/synthesisers/juce_Synthesiser.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_Synthesiser.h" -#include "../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/containers/juce_PropertySet.cpp b/src/containers/juce_PropertySet.cpp index 707e3ad356..04cd9df0d6 100644 --- a/src/containers/juce_PropertySet.cpp +++ b/src/containers/juce_PropertySet.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_PropertySet.h" -#include "../threads/juce_ScopedLock.h" #include "../text/juce_XmlDocument.h" diff --git a/src/core/juce_FileLogger.cpp b/src/core/juce_FileLogger.cpp index c79e9cc149..010fc3fc5c 100644 --- a/src/core/juce_FileLogger.cpp +++ b/src/core/juce_FileLogger.cpp @@ -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" diff --git a/src/core/juce_Singleton.h b/src/core/juce_Singleton.h index 0efafac725..23bae51630 100644 --- a/src/core/juce_Singleton.h +++ b/src/core/juce_Singleton.h @@ -26,8 +26,6 @@ #ifndef __JUCE_SINGLETON_JUCEHEADER__ #define __JUCE_SINGLETON_JUCEHEADER__ -#include "../threads/juce_ScopedLock.h" - //============================================================================== /** diff --git a/src/core/juce_StandardHeader.h b/src/core/juce_StandardHeader.h index 41e3ebfbee..8974a5f735 100644 --- a/src/core/juce_StandardHeader.h +++ b/src/core/juce_StandardHeader.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. diff --git a/src/events/juce_ActionBroadcaster.cpp b/src/events/juce_ActionBroadcaster.cpp index 0385cc3617..6daf6cace8 100644 --- a/src/events/juce_ActionBroadcaster.cpp +++ b/src/events/juce_ActionBroadcaster.cpp @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_ActionBroadcaster.h" #include "juce_MessageManager.h" -#include "../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/events/juce_InterprocessConnection.cpp b/src/events/juce_InterprocessConnection.cpp index 980cb2b3cb..7aba054dc6 100644 --- a/src/events/juce_InterprocessConnection.cpp +++ b/src/events/juce_InterprocessConnection.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_InterprocessConnection.h" -#include "../threads/juce_ScopedLock.h" #include "../memory/juce_ScopedPointer.h" diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index c86f51543c..ad115aa922 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -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" //============================================================================== diff --git a/src/events/juce_MultiTimer.h b/src/events/juce_MultiTimer.h index f3f6db024f..06a8d9387e 100644 --- a/src/events/juce_MultiTimer.h +++ b/src/events/juce_MultiTimer.h @@ -28,6 +28,7 @@ #include "juce_Timer.h" #include "../containers/juce_OwnedArray.h" +#include "../threads/juce_SpinLock.h" //============================================================================== diff --git a/src/events/juce_Timer.cpp b/src/events/juce_Timer.cpp index b38e2557a9..29583c2cf7 100644 --- a/src/events/juce_Timer.cpp +++ b/src/events/juce_Timer.cpp @@ -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" //============================================================================== diff --git a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp index d875852ca1..b63508d9db 100644 --- a/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp +++ b/src/gui/components/filebrowser/juce_DirectoryContentsList.cpp @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_DirectoryContentsList.h" #include "../../graphics/imaging/juce_ImageCache.h" -#include "../../../threads/juce_ScopedLock.h" //============================================================================== diff --git a/src/gui/components/mouse/juce_MouseCursor.cpp b/src/gui/components/mouse/juce_MouseCursor.cpp index 9b0e279269..04cdf0fd12 100644 --- a/src/gui/components/mouse/juce_MouseCursor.cpp +++ b/src/gui/components/mouse/juce_MouseCursor.cpp @@ -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" //============================================================================== diff --git a/src/gui/components/special/juce_OpenGLComponent.cpp b/src/gui/components/special/juce_OpenGLComponent.cpp index 5f3b7f14f9..71012c957b 100644 --- a/src/gui/components/special/juce_OpenGLComponent.cpp +++ b/src/gui/components/special/juce_OpenGLComponent.cpp @@ -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" //============================================================================== diff --git a/src/gui/graphics/imaging/juce_ImageCache.cpp b/src/gui/graphics/imaging/juce_ImageCache.cpp index 028e6ce0e0..e253dd60b3 100644 --- a/src/gui/graphics/imaging/juce_ImageCache.cpp +++ b/src/gui/graphics/imaging/juce_ImageCache.cpp @@ -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" diff --git a/src/io/files/juce_ZipFile.cpp b/src/io/files/juce_ZipFile.cpp index 3c21a63c09..5b30a9a8af 100644 --- a/src/io/files/juce_ZipFile.cpp +++ b/src/io/files/juce_ZipFile.cpp @@ -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" //============================================================================== diff --git a/src/io/network/juce_Socket.cpp b/src/io/network/juce_Socket.cpp index 3d8fa447aa..aef0477437 100644 --- a/src/io/network/juce_Socket.cpp +++ b/src/io/network/juce_Socket.cpp @@ -58,7 +58,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_Socket.h" -#include "../../threads/juce_ScopedLock.h" #include "../../threads/juce_Thread.h" #if JUCE_WINDOWS diff --git a/src/io/streams/juce_OutputStream.cpp b/src/io/streams/juce_OutputStream.cpp index d2241f4491..04bf4138c3 100644 --- a/src/io/streams/juce_OutputStream.cpp +++ b/src/io/streams/juce_OutputStream.cpp @@ -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" diff --git a/src/juce_core_includes.h b/src/juce_core_includes.h index 2fe2394fbf..6c12b8aaca 100644 --- a/src/juce_core_includes.h +++ b/src/juce_core_includes.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 diff --git a/src/native/linux/juce_linux_NativeCode.cpp b/src/native/linux/juce_linux_NativeCode.cpp index 0fa3622f60..04b5211a83 100644 --- a/src/native/linux/juce_linux_NativeCode.cpp +++ b/src/native/linux/juce_linux_NativeCode.cpp @@ -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" diff --git a/src/native/windows/juce_win32_Fonts.cpp b/src/native/windows/juce_win32_Fonts.cpp index bbcad25b5b..fb39674d65 100644 --- a/src/native/windows/juce_win32_Fonts.cpp +++ b/src/native/windows/juce_win32_Fonts.cpp @@ -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); diff --git a/src/text/juce_LocalisedStrings.cpp b/src/text/juce_LocalisedStrings.cpp index 4529a9f84e..54c512447f 100644 --- a/src/text/juce_LocalisedStrings.cpp +++ b/src/text/juce_LocalisedStrings.cpp @@ -28,6 +28,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_LocalisedStrings.h" +#include "../threads/juce_SpinLock.h" //============================================================================== diff --git a/src/threads/juce_CriticalSection.h b/src/threads/juce_CriticalSection.h index 0291933cc0..2006bad45c 100644 --- a/src/threads/juce_CriticalSection.h +++ b/src/threads/juce_CriticalSection.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 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 ScopedUnlockType; + + /** Provides the type of scoped try-locker to use with a CriticalSection. */ + typedef GenericScopedTryLock ScopedTryLockType; private: @@ -151,68 +152,103 @@ private: JUCE_DECLARE_NON_COPYABLE (DummyCriticalSection); }; +//============================================================================== +/** + Automatically locks and unlocks a CriticalSection object. + + Use one of these as a local variable to provide RAII-based locking of 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 +*/ +typedef CriticalSection::ScopedLockType ScopedLock; //============================================================================== /** - A simple spin-lock class that can be used as a simple, low-overhead mutex for - uncontended situations. + Automatically unlocks and re-locks 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. + This is the reverse of a ScopedLock object - instead of locking the critical + section for the lifetime of this object, it unlocks it. - @see CriticalSection -*/ -class JUCE_API SpinLock -{ -public: - inline SpinLock() throw() {} - inline ~SpinLock() throw() {} + Make sure you don't try to unlock critical sections that aren't actually locked! - void enter() const throw(); - bool tryEnter() const throw(); + e.g. @code - inline void exit() const throw() + CriticalSection myCriticalSection; + + 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 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 - //============================================================================== - /** A scoped-lock type to use with a SpinLock. */ - class ScopedLockType + @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 ScopedLockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.enter(); } - inline ~ScopedLockType() throw() { lock.exit(); } + const ScopedTryLock myScopedTryLock (myCriticalSection); - private: - //============================================================================== - const SpinLock& lock; - JUCE_DECLARE_NON_COPYABLE (ScopedLockType); - }; + // 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.. + } - //============================================================================== - /** A scoped-unlocker type to use with a SpinLock. */ - class ScopedUnlockType - { - public: - inline explicit ScopedUnlockType (const SpinLock& lock_) throw() : lock (lock_) { lock_.exit(); } - inline ~ScopedUnlockType() throw() { lock.enter(); } + // myCriticalSection gets unlocked here (if it was locked) + } + @endcode - private: - //============================================================================== - const SpinLock& lock; - JUCE_DECLARE_NON_COPYABLE (ScopedUnlockType); - }; - -private: - //============================================================================== - mutable Atomic lock; - JUCE_DECLARE_NON_COPYABLE (SpinLock); -}; + @see CriticalSection::tryEnter, ScopedLock, ScopedUnlock, ScopedReadLock +*/ +typedef CriticalSection::ScopedTryLockType ScopedTryLock; #endif // __JUCE_CRITICALSECTION_JUCEHEADER__ diff --git a/src/threads/juce_ReadWriteLock.cpp b/src/threads/juce_ReadWriteLock.cpp index 91450b5939..60b05b8d62 100644 --- a/src/threads/juce_ReadWriteLock.cpp +++ b/src/threads/juce_ReadWriteLock.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_ReadWriteLock.h" -#include "juce_ScopedLock.h" #include "juce_Thread.h" diff --git a/src/threads/juce_ReadWriteLock.h b/src/threads/juce_ReadWriteLock.h index c4badbac30..aaf179b66a 100644 --- a/src/threads/juce_ReadWriteLock.h +++ b/src/threads/juce_ReadWriteLock.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" diff --git a/src/threads/juce_ScopedLock.h b/src/threads/juce_ScopedLock.h index ee7127a597..5cb54255b3 100644 --- a/src/threads/juce_ScopedLock.h +++ b/src/threads/juce_ScopedLock.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. + + 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 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 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 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 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 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 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 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__ diff --git a/src/threads/juce_ScopedTryLock.h b/src/threads/juce_ScopedTryLock.h deleted file mode 100644 index 4b316a5e45..0000000000 --- a/src/threads/juce_ScopedTryLock.h +++ /dev/null @@ -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__ diff --git a/src/threads/juce_SpinLock.h b/src/threads/juce_SpinLock.h new file mode 100644 index 0000000000..abe78270b8 --- /dev/null +++ b/src/threads/juce_SpinLock.h @@ -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 ScopedLockType; + + /** Provides the type of scoped unlocker to use with a SpinLock. */ + typedef GenericScopedUnlock ScopedUnlockType; + +private: + //============================================================================== + mutable Atomic lock; + + JUCE_DECLARE_NON_COPYABLE (SpinLock); +}; + + +#endif // __JUCE_SPINLOCK_JUCEHEADER__ diff --git a/src/threads/juce_Thread.cpp b/src/threads/juce_Thread.cpp index 0e517688f5..c1a9820e07 100644 --- a/src/threads/juce_Thread.cpp +++ b/src/threads/juce_Thread.cpp @@ -28,7 +28,7 @@ BEGIN_JUCE_NAMESPACE #include "juce_Thread.h" -#include "juce_ScopedLock.h" +#include "juce_SpinLock.h" #include "../core/juce_Time.h" diff --git a/src/threads/juce_ThreadPool.h b/src/threads/juce_ThreadPool.h index e38ee158ce..af020a6cff 100644 --- a/src/threads/juce_ThreadPool.h +++ b/src/threads/juce_ThreadPool.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" diff --git a/src/threads/juce_TimeSliceThread.cpp b/src/threads/juce_TimeSliceThread.cpp index 7dceadbf2b..8c60ff3a2b 100644 --- a/src/threads/juce_TimeSliceThread.cpp +++ b/src/threads/juce_TimeSliceThread.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_TimeSliceThread.h" -#include "juce_ScopedLock.h" //============================================================================== diff --git a/src/utilities/juce_DeletedAtShutdown.cpp b/src/utilities/juce_DeletedAtShutdown.cpp index 96dadb1139..c9d0e2738d 100644 --- a/src/utilities/juce_DeletedAtShutdown.cpp +++ b/src/utilities/juce_DeletedAtShutdown.cpp @@ -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" //============================================================================== diff --git a/src/utilities/juce_PropertiesFile.cpp b/src/utilities/juce_PropertiesFile.cpp index 959dbb8762..b6db4a3692 100644 --- a/src/utilities/juce_PropertiesFile.cpp +++ b/src/utilities/juce_PropertiesFile.cpp @@ -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" diff --git a/src/utilities/juce_UnitTest.cpp b/src/utilities/juce_UnitTest.cpp index f42e6b3f8e..72d1eaee5d 100644 --- a/src/utilities/juce_UnitTest.cpp +++ b/src/utilities/juce_UnitTest.cpp @@ -28,7 +28,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_UnitTest.h" -#include "../threads/juce_ScopedLock.h" //==============================================================================