diff --git a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp index 0ff0a54821..3a93326562 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp +++ b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.cpp @@ -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& rect) + : left (rect.getX()), + right (rect.getRight()), + top (rect.getY()), + bottom (rect.getBottom()) +{ +} + +RelativeRectangle::RelativeRectangle (const String& stringVersion) +{ + jassertfalse // todo +} + +const Rectangle 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 (l, t, r - l, b - t); +} + +void RelativeRectangle::moveToAbsolute (const Rectangle& 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); +} diff --git a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h index 4ce4478ccd..0bc12b1f92 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_UtilityFunctions.h @@ -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& rect); + explicit RelativeRectangle (const String& stringVersion); + + const Rectangle resolve (RelativePosition::PositionFinder& positionFinder) const; + void moveToAbsolute (const Rectangle& newPos, RelativePosition::PositionFinder& positionFinder); + const String toString (int decimalPlaces) const; + + RelativePosition left, right, top, bottom; +}; diff --git a/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp b/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp index f2a6db533c..e1619bf6d6 100644 --- a/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp +++ b/extras/browser plugins/wrapper/juce_NPAPI_GlueCode.cpp @@ -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); diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index cdbae896c0..27c26b89c5 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -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 ***/ diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 90e602af6f..1c7fcccebc 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.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 ; + ScopedPointer pimpl; + CriticalSection lock; String name; - int reentrancyLevel; InterProcessLock (const InterProcessLock&); InterProcessLock& operator= (const InterProcessLock&); diff --git a/src/native/common/juce_posix_SharedCode.h b/src/native/common/juce_posix_SharedCode.h index 2f847d0a98..a7539f1763 100644 --- a/src/native/common/juce_posix_SharedCode.h +++ b/src/native/common/juce_posix_SharedCode.h @@ -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; } diff --git a/src/native/windows/juce_win32_Threads.cpp b/src/native/windows/juce_win32_Threads.cpp index 85c974163e..f7c9a14ddb 100644 --- a/src/native/windows/juce_win32_Threads.cpp +++ b/src/native/windows/juce_win32_Threads.cpp @@ -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; } diff --git a/src/threads/juce_InterProcessLock.h b/src/threads/juce_InterProcessLock.h index 202380b74e..8e5c1e0653 100644 --- a/src/threads/juce_InterProcessLock.h +++ b/src/threads/juce_InterProcessLock.h @@ -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 ; + ScopedPointer pimpl; + CriticalSection lock; String name; - int reentrancyLevel; InterProcessLock (const InterProcessLock&); InterProcessLock& operator= (const InterProcessLock&);