1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

Tarted up InterprocessLock and added a scoped lock for it. Minor safety checks in NPAPI. Jucer development.

This commit is contained in:
Julian Storer 2010-04-11 15:14:44 +02:00
parent 671dde2ffa
commit f198f06e6a
8 changed files with 666 additions and 280 deletions

View file

@ -135,7 +135,6 @@ const String hexString8Digits (int value)
return String::toHexString (value).paddedLeft ('0', 8);
}
const String createGUID (const String& seed)
{
String guid;
@ -274,43 +273,25 @@ const String replaceCEscapeChars (const String& s)
switch (c)
{
case '\t':
r << "\\t";
lastWasHexEscapeCode = false;
break;
case '\r':
r << "\\r";
lastWasHexEscapeCode = false;
break;
case '\n':
r << "\\n";
lastWasHexEscapeCode = false;
break;
case '\\':
r << "\\\\";
lastWasHexEscapeCode = false;
break;
case '\'':
r << "\\\'";
lastWasHexEscapeCode = false;
break;
case '\"':
r << "\\\"";
lastWasHexEscapeCode = false;
break;
case '\t': r << "\\t"; lastWasHexEscapeCode = false; break;
case '\r': r << "\\r"; lastWasHexEscapeCode = false; break;
case '\n': r << "\\n"; lastWasHexEscapeCode = false; break;
case '\\': r << "\\\\"; lastWasHexEscapeCode = false; break;
case '\'': r << "\\\'"; lastWasHexEscapeCode = false; break;
case '\"': r << "\\\""; lastWasHexEscapeCode = false; break;
default:
if (c < 128 &&
! (lastWasHexEscapeCode
&& String ("0123456789abcdefABCDEF").containsChar (c))) // (have to avoid following a hex escape sequence with a valid hex digit)
if (c < 128
&& ! (lastWasHexEscapeCode
&& String ("0123456789abcdefABCDEF").containsChar (c))) // (have to avoid following a hex escape sequence with a valid hex digit)
{
r << c;
lastWasHexEscapeCode = false;
}
else
{
lastWasHexEscapeCode = true;
r << "\\x" << String::toHexString ((int) c);
lastWasHexEscapeCode = true;
}
break;
@ -397,7 +378,7 @@ const String floatToCode (const float v)
{
String s ((double) (float) v, 4);
if (s.containsChar (T('.')))
if (s.containsChar ('.'))
s << 'f';
else
s << ".0f";
@ -409,7 +390,7 @@ const String doubleToCode (const double v)
{
String s (v, 7);
if (! s.containsChar (T('.')))
if (! s.containsChar ('.'))
s << ".0";
return s;
@ -422,28 +403,27 @@ const String boolToCode (const bool b)
const String colourToCode (const Colour& col)
{
#define COL(col) Colours::col,
const Colour colours[] =
{
#define COL(col) Colours::col,
#include "jucer_Colours.h"
#undef COL
Colours::transparentBlack
};
#undef COL
#define COL(col) #col,
static const char* colourNames[] =
{
#define COL(col) #col,
#include "jucer_Colours.h"
#undef COL
0
};
#undef COL
for (int i = 0; i < numElementsInArray (colourNames) - 1; ++i)
if (col == colours[i])
return "Colours::" + String (colourNames[i]);
return "Colour (0x" + hexString8Digits ((int) col.getARGB()) + T(')');
return "Colour (0x" + hexString8Digits ((int) col.getARGB()) + ')';
}
const String justificationToCode (const Justification& justification)
@ -523,3 +503,154 @@ int indexOfLineStartingWith (const StringArray& lines, const String& text, int s
return -1;
}
//==============================================================================
RelativePosition::RelativePosition()
: value (0), isRelative (false)
{
}
RelativePosition::RelativePosition (double absoluteDistanceFromOrigin)
: value (absoluteDistanceFromOrigin), isRelative (false)
{
}
RelativePosition::RelativePosition (double absoluteDistance, const String& source)
: nameOfSource1 (source), value (absoluteDistance), isRelative (false)
{
}
RelativePosition::RelativePosition (double relativeProportion, const String& pos1, const String& pos2)
: nameOfSource1 (pos1), nameOfSource2 (pos2), value (relativeProportion), isRelative (true)
{
}
RelativePosition::~RelativePosition()
{
}
bool RelativePosition::isOrigin (const String& name)
{
return name.isEmpty() || name == parentOriginMarkerName;
}
const String RelativePosition::checkName (const String& name)
{
return name.isEmpty() ? parentOriginMarkerName : name;
}
double RelativePosition::getPosition (const String& name, PositionFinder& positionFinder) const
{
if (isOrigin (name))
return 0.0;
RelativePosition* const pos = positionFinder.findPosition (nameOfSource1);
if (pos != 0)
return pos->resolve (positionFinder);
jassertfalse;
return 0.0;
}
double RelativePosition::resolve (PositionFinder& positionFinder) const
{
const double pos1 = getPos1 (positionFinder);
return isRelative ? pos1 + (getPos2 (positionFinder) - pos1) * value
: pos1 + value;
}
void RelativePosition::moveToAbsolute (double newPos, PositionFinder& positionFinder)
{
const double pos1 = getPos1 (positionFinder);
if (isRelative)
value = (newPos - pos1) / (getPos2 (positionFinder) - pos1);
else
value = newPos - pos1;
}
RelativePosition::RelativePosition (const String& stringVersion)
{
jassertfalse //todo
}
const String RelativePosition::toString (int decimalPlaces) const
{
if (isRelative)
{
const String percent (value * 100.0, 2);
if (isOrigin (nameOfSource1))
{
if (nameOfSource2 == parentExtentMarkerName)
return percent + "%";
else
return percent + "% of " + checkName (nameOfSource2);
}
else
return percent + "% of " + checkName (nameOfSource1) + " to " + checkName (nameOfSource2);
}
else
{
if (isOrigin (nameOfSource1))
return String (value, decimalPlaces);
else if (value != 0)
return checkName (nameOfSource1) + " + " + String (value, decimalPlaces);
else
return checkName (nameOfSource1);
}
}
const char* RelativePosition::parentOriginMarkerName = "origin";
const char* RelativePosition::parentExtentMarkerName = "size";
//==============================================================================
RelativeRectangle::RelativeRectangle()
{
}
RelativeRectangle::RelativeRectangle (const Rectangle<int>& rect)
: left (rect.getX()),
right (rect.getRight()),
top (rect.getY()),
bottom (rect.getBottom())
{
}
RelativeRectangle::RelativeRectangle (const String& stringVersion)
{
jassertfalse // todo
}
const Rectangle<int> RelativeRectangle::resolve (RelativePosition::PositionFinder& positionFinder) const
{
const int l = roundToInt (left.resolve (positionFinder));
const int r = roundToInt (right.resolve (positionFinder));
const int t = roundToInt (top.resolve (positionFinder));
const int b = roundToInt (bottom.resolve (positionFinder));
return Rectangle<int> (l, t, r - l, b - t);
}
void RelativeRectangle::moveToAbsolute (const Rectangle<int>& newPos, RelativePosition::PositionFinder& positionFinder)
{
left.moveToAbsolute (newPos.getX(), positionFinder);
right.moveToAbsolute (newPos.getRight(), positionFinder);
top.moveToAbsolute (newPos.getY(), positionFinder);
bottom.moveToAbsolute (newPos.getBottom(), positionFinder);
// do it all again in case there were dependencies between some of the positions..
left.moveToAbsolute (newPos.getX(), positionFinder);
right.moveToAbsolute (newPos.getRight(), positionFinder);
top.moveToAbsolute (newPos.getY(), positionFinder);
bottom.moveToAbsolute (newPos.getBottom(), positionFinder);
}
const String RelativeRectangle::toString (int decimalPlaces) const
{
return left.toString (decimalPlaces) + ", " + top.toString (decimalPlaces)
+ ", " + right.toString (decimalPlaces) + ", " + bottom.toString (decimalPlaces);
}

View file

@ -108,3 +108,59 @@ private:
Time fileModificationTime;
int64 fileHashCode, fileSize;
};
//==============================================================================
class RelativePosition
{
public:
RelativePosition();
explicit RelativePosition (const String& stringVersion);
explicit RelativePosition (double absoluteDistanceFromOrigin);
RelativePosition (double absoluteDistance, const String& source);
RelativePosition (double relativeProportion, const String& pos1, const String& pos2);
~RelativePosition();
class PositionFinder
{
public:
virtual ~PositionFinder() {}
virtual RelativePosition* findPosition (const String& name) = 0;
};
const String getName() const { return name; }
void setName (const String& newName) { name = newName; }
double resolve (PositionFinder& positionFinder) const;
void moveToAbsolute (double newPos, PositionFinder& positionFinder);
const String toString (int decimalPlaces) const;
static const char* parentOriginMarkerName;
static const char* parentExtentMarkerName;
private:
String name, nameOfSource1, nameOfSource2;
double value;
bool isRelative;
double getPos1 (PositionFinder& positionFinder) const { return getPosition (nameOfSource1, positionFinder); }
double getPos2 (PositionFinder& positionFinder) const { return getPosition (nameOfSource2, positionFinder); }
double getPosition (const String& name, PositionFinder& positionFinder) const;
static const String checkName (const String& name);
static bool isOrigin (const String& name);
};
class RelativeRectangle
{
public:
RelativeRectangle();
explicit RelativeRectangle (const Rectangle<int>& rect);
explicit RelativeRectangle (const String& stringVersion);
const Rectangle<int> resolve (RelativePosition::PositionFinder& positionFinder) const;
void moveToAbsolute (const Rectangle<int>& newPos, RelativePosition::PositionFinder& positionFinder);
const String toString (int decimalPlaces) const;
RelativePosition left, right, top, bottom;
};

View file

@ -849,7 +849,7 @@ static const var createValueFromNPVariant (NPP npp, const NPVariant& v)
return var (String::fromUTF8 ((const char*) (NPVARIANT_TO_STRING (v).utf8characters),
(int) NPVARIANT_TO_STRING (v).utf8length));
#endif
else if (NPVARIANT_IS_OBJECT (v))
else if (NPVARIANT_IS_OBJECT (v) && npp != 0)
return var (new DynamicObjectWrappingNPObject (npp, NPVARIANT_TO_OBJECT (v)));
return var();
@ -872,7 +872,7 @@ static void createNPVariantFromValue (NPP npp, NPVariant& out, const var& v)
memcpy (stringCopy, utf8, utf8Len);
STRINGZ_TO_NPVARIANT (stringCopy, out);
}
else if (v.isObject())
else if (v.isObject() && npp != 0)
OBJECT_TO_NPVARIANT (NPObjectWrappingDynamicObject::create (npp, v), out);
else
VOID_TO_NPVARIANT (out);

View file

@ -211735,48 +211735,89 @@ void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name)
return (h != 0) ? (void*) GetProcAddress ((HMODULE) h, name.toCString()) : 0;
}
class InterProcessLock::Pimpl
{
public:
Pimpl (const String& name, const int timeOutMillisecs)
: handle (0), refCount (1)
{
handle = CreateMutex (0, TRUE, "Global\\" + name.replaceCharacter ('\\','/'));
if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
{
if (timeOutMillisecs == 0)
{
close();
return;
}
switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs))
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
break;
case WAIT_TIMEOUT:
default:
close();
break;
}
}
}
~Pimpl()
{
close();
}
void close()
{
if (handle != 0)
{
ReleaseMutex (handle);
CloseHandle (handle);
handle = 0;
}
}
HANDLE handle;
int refCount;
};
InterProcessLock::InterProcessLock (const String& name_)
: internal (0),
name (name_),
reentrancyLevel (0)
: name (name_)
{
}
InterProcessLock::~InterProcessLock()
{
exit();
}
bool InterProcessLock::enter (const int timeOutMillisecs)
{
if (reentrancyLevel++ == 0)
{
internal = CreateMutex (0, TRUE, "Global\\" + name);
const ScopedLock sl (lock);
if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
{
if (timeOutMillisecs == 0
|| WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs)
== WAIT_TIMEOUT)
{
ReleaseMutex (internal);
CloseHandle (internal);
internal = 0;
}
}
if (pimpl == 0)
{
pimpl = new Pimpl (name, timeOutMillisecs);
if (pimpl->handle == 0)
pimpl = 0;
}
else
{
pimpl->refCount++;
}
return (internal != 0);
return pimpl != 0;
}
void InterProcessLock::exit()
{
if (--reentrancyLevel == 0 && internal != 0)
{
ReleaseMutex (internal);
CloseHandle (internal);
internal = 0;
}
const ScopedLock sl (lock);
if (pimpl != 0 && --(pimpl->refCount) == 0)
pimpl = 0;
}
#endif
@ -227896,88 +227937,110 @@ const String juce_getOutputFromCommand (const String& command)
return result;
}
InterProcessLock::InterProcessLock (const String& name_)
: internal (0),
name (name_),
reentrancyLevel (0)
class InterProcessLock::Pimpl
{
public:
Pimpl (const String& name, const int timeOutMillisecs)
: handle (0), refCount (1)
{
#if JUCE_MAC
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
#else
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
#endif
temp.create();
handle = open (temp.getFullPathName().toUTF8(), O_RDWR);
temp.create();
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
internal = open (temp.getFullPathName().toUTF8(), O_RDWR);
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
for (;;)
{
const int result = fcntl (handle, F_SETLK, &fl);
if (result >= 0)
return;
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
}
}
closeFile();
}
~Pimpl()
{
closeFile();
}
void closeFile()
{
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
while (! (fcntl (handle, F_SETLKW, &fl) >= 0 || errno != EINTR))
{}
close (handle);
handle = 0;
}
}
int handle, refCount;
};
InterProcessLock::InterProcessLock (const String& name_)
: name (name_)
{
}
InterProcessLock::~InterProcessLock()
{
while (reentrancyLevel > 0)
this->exit();
close (internal);
}
bool InterProcessLock::enter (const int timeOutMillisecs)
{
if (internal == 0)
return false;
const ScopedLock sl (lock);
if (reentrancyLevel != 0)
return true;
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
for (;;)
if (pimpl == 0)
{
const int result = fcntl (internal, F_SETLK, &fl);
pimpl = new Pimpl (name, timeOutMillisecs);
if (result >= 0)
{
++reentrancyLevel;
return true;
}
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
if (pimpl->handle == 0)
pimpl = 0;
}
else
{
pimpl->refCount++;
}
return false;
return pimpl != 0;
}
void InterProcessLock::exit()
{
if (reentrancyLevel > 0 && internal != 0)
{
--reentrancyLevel;
const ScopedLock sl (lock);
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
for (;;)
{
const int result = fcntl (internal, F_SETLKW, &fl);
if (result >= 0 || errno != EINTR)
break;
}
}
if (pimpl != 0 && --(pimpl->refCount) == 0)
pimpl = 0;
}
/*** End of inlined file: juce_posix_SharedCode.h ***/
@ -237921,88 +237984,110 @@ const String juce_getOutputFromCommand (const String& command)
return result;
}
InterProcessLock::InterProcessLock (const String& name_)
: internal (0),
name (name_),
reentrancyLevel (0)
class InterProcessLock::Pimpl
{
public:
Pimpl (const String& name, const int timeOutMillisecs)
: handle (0), refCount (1)
{
#if JUCE_MAC
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
#else
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
#endif
temp.create();
handle = open (temp.getFullPathName().toUTF8(), O_RDWR);
temp.create();
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
internal = open (temp.getFullPathName().toUTF8(), O_RDWR);
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
for (;;)
{
const int result = fcntl (handle, F_SETLK, &fl);
if (result >= 0)
return;
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
}
}
closeFile();
}
~Pimpl()
{
closeFile();
}
void closeFile()
{
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
while (! (fcntl (handle, F_SETLKW, &fl) >= 0 || errno != EINTR))
{}
close (handle);
handle = 0;
}
}
int handle, refCount;
};
InterProcessLock::InterProcessLock (const String& name_)
: name (name_)
{
}
InterProcessLock::~InterProcessLock()
{
while (reentrancyLevel > 0)
this->exit();
close (internal);
}
bool InterProcessLock::enter (const int timeOutMillisecs)
{
if (internal == 0)
return false;
const ScopedLock sl (lock);
if (reentrancyLevel != 0)
return true;
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
for (;;)
if (pimpl == 0)
{
const int result = fcntl (internal, F_SETLK, &fl);
pimpl = new Pimpl (name, timeOutMillisecs);
if (result >= 0)
{
++reentrancyLevel;
return true;
}
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
if (pimpl->handle == 0)
pimpl = 0;
}
else
{
pimpl->refCount++;
}
return false;
return pimpl != 0;
}
void InterProcessLock::exit()
{
if (reentrancyLevel > 0 && internal != 0)
{
--reentrancyLevel;
const ScopedLock sl (lock);
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
for (;;)
{
const int result = fcntl (internal, F_SETLKW, &fl);
if (result >= 0 || errno != EINTR)
break;
}
}
if (pimpl != 0 && --(pimpl->refCount) == 0)
pimpl = 0;
}
/*** End of inlined file: juce_posix_SharedCode.h ***/

View file

@ -8719,20 +8719,32 @@ public:
void exit();
class ScopedLockType
{
public:
inline explicit ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lock.enter(); }
inline ~ScopedLockType() { lock_.exit(); }
private:
InterProcessLock& lock_;
ScopedLockType (const ScopedLockType&);
ScopedLockType& operator= (const ScopedLockType&);
};
juce_UseDebuggingNewOperator
private:
#if JUCE_WINDOWS
void* internal;
// #elif JUCE_64BIT
// long long internal;
#else
int internal;
#endif
class Pimpl;
friend class ScopedPointer <Pimpl>;
ScopedPointer <Pimpl> pimpl;
CriticalSection lock;
String name;
int reentrancyLevel;
InterProcessLock (const InterProcessLock&);
InterProcessLock& operator= (const InterProcessLock&);

View file

@ -462,87 +462,110 @@ const String juce_getOutputFromCommand (const String& command)
return result;
}
//==============================================================================
InterProcessLock::InterProcessLock (const String& name_)
: internal (0),
name (name_),
reentrancyLevel (0)
class InterProcessLock::Pimpl
{
public:
Pimpl (const String& name, const int timeOutMillisecs)
: handle (0), refCount (1)
{
#if JUCE_MAC
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
// (don't use getSpecialLocation() to avoid the temp folder being different for each app)
const File temp (File ("~/Library/Caches/Juce").getChildFile (name));
#else
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
const File temp (File::getSpecialLocation (File::tempDirectory).getChildFile (name));
#endif
temp.create();
handle = open (temp.getFullPathName().toUTF8(), O_RDWR);
temp.create();
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
internal = open (temp.getFullPathName().toUTF8(), O_RDWR);
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
for (;;)
{
const int result = fcntl (handle, F_SETLK, &fl);
if (result >= 0)
return;
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
}
}
closeFile();
}
~Pimpl()
{
closeFile();
}
void closeFile()
{
if (handle != 0)
{
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
while (! (fcntl (handle, F_SETLKW, &fl) >= 0 || errno != EINTR))
{}
close (handle);
handle = 0;
}
}
int handle, refCount;
};
InterProcessLock::InterProcessLock (const String& name_)
: name (name_)
{
}
InterProcessLock::~InterProcessLock()
{
while (reentrancyLevel > 0)
this->exit();
close (internal);
}
bool InterProcessLock::enter (const int timeOutMillisecs)
{
if (internal == 0)
return false;
const ScopedLock sl (lock);
if (reentrancyLevel != 0)
return true;
const int64 endTime = Time::currentTimeMillis() + timeOutMillisecs;
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_WRLCK;
for (;;)
if (pimpl == 0)
{
const int result = fcntl (internal, F_SETLK, &fl);
pimpl = new Pimpl (name, timeOutMillisecs);
if (result >= 0)
{
++reentrancyLevel;
return true;
}
if (errno != EINTR)
{
if (timeOutMillisecs == 0
|| (timeOutMillisecs > 0 && Time::currentTimeMillis() >= endTime))
break;
Thread::sleep (10);
}
if (pimpl->handle == 0)
pimpl = 0;
}
else
{
pimpl->refCount++;
}
return false;
return pimpl != 0;
}
void InterProcessLock::exit()
{
if (reentrancyLevel > 0 && internal != 0)
{
--reentrancyLevel;
const ScopedLock sl (lock);
struct flock fl;
zerostruct (fl);
fl.l_whence = SEEK_SET;
fl.l_type = F_UNLCK;
for (;;)
{
const int result = fcntl (internal, F_SETLKW, &fl);
if (result >= 0 || errno != EINTR)
break;
}
}
if (pimpl != 0 && --(pimpl->refCount) == 0)
pimpl = 0;
}

View file

@ -337,48 +337,89 @@ void* PlatformUtilities::getProcedureEntryPoint (void* h, const String& name)
//==============================================================================
class InterProcessLock::Pimpl
{
public:
Pimpl (const String& name, const int timeOutMillisecs)
: handle (0), refCount (1)
{
handle = CreateMutex (0, TRUE, "Global\\" + name.replaceCharacter ('\\','/'));
if (handle != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
{
if (timeOutMillisecs == 0)
{
close();
return;
}
switch (WaitForSingleObject (handle, timeOutMillisecs < 0 ? INFINITE : timeOutMillisecs))
{
case WAIT_OBJECT_0:
case WAIT_ABANDONED:
break;
case WAIT_TIMEOUT:
default:
close();
break;
}
}
}
~Pimpl()
{
close();
}
void close()
{
if (handle != 0)
{
ReleaseMutex (handle);
CloseHandle (handle);
handle = 0;
}
}
HANDLE handle;
int refCount;
};
InterProcessLock::InterProcessLock (const String& name_)
: internal (0),
name (name_),
reentrancyLevel (0)
: name (name_)
{
}
InterProcessLock::~InterProcessLock()
{
exit();
}
bool InterProcessLock::enter (const int timeOutMillisecs)
{
if (reentrancyLevel++ == 0)
{
internal = CreateMutex (0, TRUE, "Global\\" + name);
const ScopedLock sl (lock);
if (internal != 0 && GetLastError() == ERROR_ALREADY_EXISTS)
{
if (timeOutMillisecs == 0
|| WaitForSingleObject (internal, (timeOutMillisecs < 0) ? INFINITE : timeOutMillisecs)
== WAIT_TIMEOUT)
{
ReleaseMutex (internal);
CloseHandle (internal);
internal = 0;
}
}
if (pimpl == 0)
{
pimpl = new Pimpl (name, timeOutMillisecs);
if (pimpl->handle == 0)
pimpl = 0;
}
else
{
pimpl->refCount++;
}
return (internal != 0);
return pimpl != 0;
}
void InterProcessLock::exit()
{
if (--reentrancyLevel == 0 && internal != 0)
{
ReleaseMutex (internal);
CloseHandle (internal);
internal = 0;
}
const ScopedLock sl (lock);
if (pimpl != 0 && --(pimpl->refCount) == 0)
pimpl = 0;
}

View file

@ -27,7 +27,7 @@
#define __JUCE_INTERPROCESSLOCK_JUCEHEADER__
#include "../text/juce_String.h"
#include "../containers/juce_ScopedPointer.h"
//==============================================================================
/**
@ -67,22 +67,60 @@ public:
*/
void exit();
//==============================================================================
/**
Automatically locks and unlocks an InterProcessLock object.
This works like a ScopedLock, but using an InterprocessLock rather than
a CriticalSection.
@see ScopedLock
*/
class ScopedLockType
{
public:
//==============================================================================
/** Creates a scoped lock.
As soon as it is created, this will lock the InterProcessLock, and
when the ScopedLockType object is deleted, the InterProcessLock 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 ScopedLockType (InterProcessLock& lock) : lock_ (lock) { lock.enter(); }
/** Destructor.
The InterProcessLock 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 ~ScopedLockType() { lock_.exit(); }
private:
//==============================================================================
InterProcessLock& lock_;
ScopedLockType (const ScopedLockType&);
ScopedLockType& operator= (const ScopedLockType&);
};
//==============================================================================
juce_UseDebuggingNewOperator
private:
//==============================================================================
#if JUCE_WINDOWS
void* internal;
// #elif JUCE_64BIT
// long long internal;
#else
int internal;
#endif
class Pimpl;
friend class ScopedPointer <Pimpl>;
ScopedPointer <Pimpl> pimpl;
CriticalSection lock;
String name;
int reentrancyLevel;
InterProcessLock (const InterProcessLock&);
InterProcessLock& operator= (const InterProcessLock&);