@@ -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" | |||
//============================================================================== | |||