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:
parent
671dde2ffa
commit
f198f06e6a
8 changed files with 666 additions and 280 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 ***/
|
||||
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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&);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue