diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj index 64696c98a1..e41cd85336 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2005/The Jucer.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\Jucer.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj index d4e7960493..483a2fbd48 100644 --- a/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj +++ b/extras/Jucer (experimental)/Builds/VisualStudio2008/The Jucer.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\Jucer.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h index 2ebcfa8b1d..a14f86a888 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExport_MSVC.h @@ -526,9 +526,7 @@ private: linker->setAttribute ("EnableCOMDATFolding", "2"); } - linker->setAttribute ("RandomizedBaseAddress", "1"); - linker->setAttribute ("DataExecutionPrevention", "0"); - linker->setAttribute ("TargetMachine", "1"); + linker->setAttribute ("TargetMachine", "1"); // (64-bit build = 5) String extraLinkerOptions (getExtraLinkerFlags().toString()); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.cpp b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.cpp index f4939d236f..b18cf3556e 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.cpp +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.cpp @@ -115,6 +115,28 @@ const File ProjectExporter::getTargetFolder() const return project.resolveFilename (getTargetLocation().toString()); } +const String ProjectExporter::getIncludePathForFileInJuceFolder (const String& pathFromJuceFolder, const File& targetIncludeFile) const +{ + String juceFolderPath (getJuceFolder().toString()); + + if (juceFolderPath.startsWithChar ('<')) + { + juceFolderPath = unixStylePath (File::addTrailingSeparator (juceFolderPath.substring (1).dropLastCharacters(1))); + if (juceFolderPath == "/") + juceFolderPath = String::empty; + + return "<" + juceFolderPath + pathFromJuceFolder + ">"; + } + else + { + const RelativePath juceFromProject (juceFolderPath, RelativePath::projectFolder); + const RelativePath fileFromProject (juceFromProject.getChildFile (pathFromJuceFolder)); + const RelativePath fileFromHere (fileFromProject.rebased (project.getFile().getParentDirectory(), + targetIncludeFile.getParentDirectory(), RelativePath::unknown)); + return fileFromHere.toUnixStyle().quoted(); + } +} + const RelativePath ProjectExporter::getJucePathFromTargetFolder() const { RelativePath juceFolder (getJuceFolder().toString(), RelativePath::projectFolder); diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h index 87def6586f..b36174067a 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectExporter.h @@ -78,6 +78,9 @@ public: Value getExtraCompilerFlags() const { return getSetting ("extraCompilerFlags"); } Value getExtraLinkerFlags() const { return getSetting ("extraLinkerFlags"); } + // This adds the quotes, and may return angle-brackets, eg: or normal quotes. + const String getIncludePathForFileInJuceFolder (const String& pathFromJuceFolder, const File& targetIncludeFile) const; + Array juceWrapperFiles; protected: @@ -87,6 +90,7 @@ protected: String name; const RelativePath getJucePathFromTargetFolder() const; + const String getDefaultBuildsRootFolder() const { return "Builds/"; } const Array getVSTFilesRequired() const; diff --git a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h index 1d70cc7aa9..96332315e2 100644 --- a/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h +++ b/extras/Jucer (experimental)/Source/model/Project/jucer_ProjectSaver.h @@ -251,12 +251,7 @@ private: if (exporter != 0) { - const RelativePath juceFromProject (exporter->getJuceFolder().toString(), RelativePath::projectFolder); - const RelativePath fileFromProject (juceFromProject.getChildFile (pathFromJuceFolder)); - const RelativePath fileFromHere (fileFromProject.rebased (project.getFile().getParentDirectory(), - juceHeaderFile.getParentDirectory(), RelativePath::unknown)); - - paths.add (fileFromHere.toUnixStyle()); + paths.add (exporter->getIncludePathForFileInJuceFolder (pathFromJuceFolder, juceHeaderFile)); guards.add (exporter->getOSTestMacro()); } } @@ -266,7 +261,7 @@ private: if (uniquePaths.size() == 1) { - out << "#include " << paths[0].quoted() << newLine; + out << "#include " << paths[0] << newLine; } else { @@ -286,7 +281,7 @@ private: for (i = 0; i < paths.size(); ++i) { out << (i == 0 ? "#if " : "#elif ") << guards[i] << newLine - << " #include " << paths[i].quoted() << newLine; + << " #include " << paths[i] << newLine; } out << "#endif" << newLine; diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp index c61f5680e6..a4d04dec0d 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorCanvas.cpp @@ -386,6 +386,7 @@ public: markerRootY.removeListener (this); getSelection().removeChangeListener (this); + resizers.clear(); deleteAllChildren(); } @@ -497,6 +498,7 @@ public: void resized() { updateMarkers(); + updateResizeFrames(); } void changeListenerCallback (void*) @@ -543,16 +545,19 @@ public: for (i = 0; i < num; ++i) requiredIds.add (selection.getSelectedItem(i)); - for (i = getNumChildComponents(); --i >= 0;) + for (i = resizers.size(); --i >= 0;) { - ResizeFrame* resizer = dynamic_cast (getChildComponent(i)); + ResizeFrame* resizer = resizers.getUnchecked(i); + const int index = requiredIds.indexOf (resizer->getTargetObjectID()); - if (resizer != 0) + if (index >= 0) { - if (selection.isSelected (resizer->getTargetObjectID())) - requiredIds.removeString (resizer->getTargetObjectID()); - else - delete resizer; + resizer->updatePosition(); + requiredIds.remove (index); + } + else + { + resizers.remove (i); } } @@ -563,6 +568,7 @@ public: if (state.isValid()) // (the id may be a marker) { ResizeFrame* frame = new ResizeFrame (canvas, requiredIds[i], state); + resizers.add (frame); addAndMakeVisible (frame); frame->updatePosition(); } @@ -576,6 +582,7 @@ private: ScopedPointer > lasso; bool mouseDownResult, isDraggingClickedComp; SelectedItems::ItemType mouseDownCompUID; + OwnedArray resizers; void updateMarkers (bool isX) { diff --git a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h index 165563307e..1444abda85 100644 --- a/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h +++ b/extras/Jucer (experimental)/Source/ui/Editor Base/jucer_EditorDragOperation.h @@ -80,7 +80,7 @@ public: if (isDraggingLeftRight()) { verticalSnapTargets.add (SnapLine (0, -100.0f, 10000.0f)); - verticalSnapTargets.add (SnapLine (getCanvasWidth(), -100.0f, 10000.0f)); + verticalSnapTargets.add (SnapLine ((float) getCanvasWidth(), -100.0f, 10000.0f)); if (zone.isDraggingWholeObject() || (zone.isDraggingLeftEdge() && zone.isDraggingRightEdge())) verticalSnapTargets.add (SnapLine ((float) getCanvasWidth() / 2.0f, 0, 10000.0f)); @@ -89,7 +89,7 @@ public: if (isDraggingUpDown()) { horizontalSnapTargets.add (SnapLine (0, -100.0f, 10000.0f)); - horizontalSnapTargets.add (SnapLine (getCanvasHeight(), -100.0f, 10000.0f)); + horizontalSnapTargets.add (SnapLine ((float) getCanvasHeight(), -100.0f, 10000.0f)); if (zone.isDraggingWholeObject() || (zone.isDraggingTopEdge() && zone.isDraggingBottomEdge())) horizontalSnapTargets.add (SnapLine ((float) getCanvasHeight() / 2.0f, 0, 10000.0f)); diff --git a/extras/Jucer (experimental)/Source/utility/jucer_ColourEditorComponent.h b/extras/Jucer (experimental)/Source/utility/jucer_ColourEditorComponent.h index 93450dcd95..3d58cdae03 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_ColourEditorComponent.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_ColourEditorComponent.h @@ -206,12 +206,12 @@ private: return StoredSettings::getInstance()->swatchColours.size(); } - const Colour getSwatchColour (const int index) const + const Colour getSwatchColour (int index) const { return StoredSettings::getInstance()->swatchColours [index]; } - void setSwatchColour (const int index, const Colour& newColour) const + void setSwatchColour (int index, const Colour& newColour) const { StoredSettings::getInstance()->swatchColours.set (index, newColour); } diff --git a/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h b/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h index ba322dca45..2bcb184069 100644 --- a/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h +++ b/extras/Jucer (experimental)/Source/utility/jucer_MarkerListBase.h @@ -40,10 +40,12 @@ public: ValueTree getMarker (int index) const { return group.getChild (index); } ValueTree getMarkerNamed (const String& name) const { return group.getChildWithProperty (getMarkerNameProperty(), name); } bool contains (const ValueTree& markerState) const { return markerState.isAChildOf (group); } - const Coordinate getCoordinate (const ValueTree& markerState) const { return Coordinate (markerState [getMarkerNameProperty()].toString(), isX); } + const String getName (const ValueTree& markerState) const { return markerState [getMarkerNameProperty()].toString(); } Value getNameAsValue (const ValueTree& markerState) const { return markerState.getPropertyAsValue (getMarkerNameProperty(), getUndoManager()); } - void setCoordinate (ValueTree& markerState, const Coordinate& newCoord) { markerState.setProperty (getMarkerNameProperty(), newCoord.toString(), getUndoManager()); } + + const Coordinate getCoordinate (const ValueTree& markerState) const { return Coordinate (markerState [getMarkerPosProperty()].toString(), isX); } + void setCoordinate (ValueTree& markerState, const Coordinate& newCoord) { markerState.setProperty (getMarkerPosProperty(), newCoord.toString(), getUndoManager()); } void createMarker (const String& name, int position) { diff --git a/extras/amalgamator/Builds/VisualStudio2005/Amalgamator.vcproj b/extras/amalgamator/Builds/VisualStudio2005/Amalgamator.vcproj index 02303395ea..f8ead20775 100644 --- a/extras/amalgamator/Builds/VisualStudio2005/Amalgamator.vcproj +++ b/extras/amalgamator/Builds/VisualStudio2005/Amalgamator.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\amalgamator.pdb" SubSystem="1" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/amalgamator/Builds/VisualStudio2008/Amalgamator.vcproj b/extras/amalgamator/Builds/VisualStudio2008/Amalgamator.vcproj index 1b67708a15..1972640dc1 100644 --- a/extras/amalgamator/Builds/VisualStudio2008/Amalgamator.vcproj +++ b/extras/amalgamator/Builds/VisualStudio2008/Amalgamator.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\amalgamator.pdb" SubSystem="1" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj index 537dd2553c..b4daf47447 100644 --- a/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2005/Plugin Host.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\Plugin Host.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj index 06d4132847..8a12df5457 100644 --- a/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj +++ b/extras/audio plugin host/Builds/VisualStudio2008/Plugin Host.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\Plugin Host.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/audio plugins/demo/Builds/VisualStudio2005/JuceDemoPlugin.vcproj b/extras/audio plugins/demo/Builds/VisualStudio2005/JuceDemoPlugin.vcproj index a3b74cfca9..b7fa377df7 100644 --- a/extras/audio plugins/demo/Builds/VisualStudio2005/JuceDemoPlugin.vcproj +++ b/extras/audio plugins/demo/Builds/VisualStudio2005/JuceDemoPlugin.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/audio plugins/demo/Builds/VisualStudio2008/JuceDemoPlugin.vcproj b/extras/audio plugins/demo/Builds/VisualStudio2008/JuceDemoPlugin.vcproj index 24634d48bc..9f0f0f872a 100644 --- a/extras/audio plugins/demo/Builds/VisualStudio2008/JuceDemoPlugin.vcproj +++ b/extras/audio plugins/demo/Builds/VisualStudio2008/JuceDemoPlugin.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/binarybuilder/Builds/VisualStudio2005/BinaryBuilder.vcproj b/extras/binarybuilder/Builds/VisualStudio2005/BinaryBuilder.vcproj index 84b05a8e88..7f86ecfec3 100644 --- a/extras/binarybuilder/Builds/VisualStudio2005/BinaryBuilder.vcproj +++ b/extras/binarybuilder/Builds/VisualStudio2005/BinaryBuilder.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" SubSystem="1" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/binarybuilder/Builds/VisualStudio2008/BinaryBuilder.vcproj b/extras/binarybuilder/Builds/VisualStudio2008/BinaryBuilder.vcproj index 857b85baf4..fa7242cee8 100644 --- a/extras/binarybuilder/Builds/VisualStudio2008/BinaryBuilder.vcproj +++ b/extras/binarybuilder/Builds/VisualStudio2008/BinaryBuilder.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" SubSystem="1" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj b/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj index fe16774b9d..6b03dd6c54 100644 --- a/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj +++ b/extras/example projects/Builds/VisualStudio2005/HelloWorld.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\HelloWorld.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj b/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj index 96dd24a5c8..7474258d9a 100644 --- a/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj +++ b/extras/example projects/Builds/VisualStudio2008/HelloWorld.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\HelloWorld.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj b/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj index 83e203a5df..14e2fab842 100644 --- a/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj +++ b/extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\JuceDemo.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj b/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj index f7f06ff1d2..21144e1332 100644 --- a/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj +++ b/extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj @@ -54,8 +54,6 @@ GenerateDebugInformation="true" ProgramDatabaseFile=".\Debug\JuceDemo.pdb" SubSystem="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> @@ -115,8 +113,6 @@ GenerateManifest="false" OptimizeReferences="2" EnableCOMDATFolding="2" - RandomizedBaseAddress="1" - DataExecutionPrevention="0" TargetMachine="1"/> diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 77312ba8f8..120df76270 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -1444,6 +1444,54 @@ const StringArray SystemStats::getMACAddressStrings() static bool juceInitialisedNonGUI = false; +#if JUCE_DEBUG +template +static void juce_testAtomicType (Type) +{ + Atomic a; + a.set ((Type) 10); + a += (Type) 15; + a.memoryBarrier(); + a -= (Type) 5; + ++a; + ++a; + --a; + a.memoryBarrier(); + + /* These are some simple test cases to check the atomics - let me know + if any of these assertions fail on your system! + */ + jassert (a.get() == (Type) 21); + jassert (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21); + jassert (a.get() == (Type) 21); + jassert (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21); + jassert (a.get() == (Type) 101); + jassert (! a.compareAndSetBool ((Type) 300, (Type) 200)); + jassert (a.get() == (Type) 101); + jassert (a.compareAndSetBool ((Type) 200, a.get())); + jassert (a.get() == (Type) 200); + + jassert (a.exchange ((Type) 300) == (Type) 200); + jassert (a.get() == (Type) 300); +} + +static void juce_testAtomics() +{ + juce_testAtomicType ((int) 0); + juce_testAtomicType ((unsigned int) 0); + juce_testAtomicType ((int32) 0); + juce_testAtomicType ((uint32) 0); + juce_testAtomicType ((long) 0); + juce_testAtomicType ((void*) 0); + juce_testAtomicType ((int*) 0); + #if ! (JUCE_WINDOWS && JUCE_32BIT) // some 64-bit intrinsics aren't available on win32 + juce_testAtomicType ((int64) 0); + juce_testAtomicType ((uint64) 0); + #endif + +} +#endif + void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() { if (! juceInitialisedNonGUI) @@ -1473,11 +1521,7 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() int a2[3]; jassert (numElementsInArray(a2) == 3); - int n = 1; - Atomic::increment (n); - jassert (Atomic::incrementAndReturn (n) == 3); - Atomic::decrement (n); - jassert (Atomic::decrementAndReturn (n) == 1); + juce_testAtomics(); jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); @@ -9962,7 +10006,7 @@ public: static juce_wchar* createUninitialised (const size_t numChars) { StringHolder* const s = reinterpret_cast (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); - s->refCount = 0; + s->refCount.value = 0; s->allocatedNumChars = numChars; return &(s->text[0]); } @@ -9989,12 +10033,12 @@ public: static void retain (juce_wchar* const text) throw() { - Atomic::increment (bufferFromText (text)->refCount); + ++(bufferFromText (text)->refCount); } static inline void release (StringHolder* const b) throw() { - if (Atomic::decrementAndReturn (b->refCount) == -1 && b != &empty) + if (--(b->refCount) == -1 && b != &empty) delete[] reinterpret_cast (b); } @@ -10007,7 +10051,7 @@ public: { StringHolder* const b = bufferFromText (text); - if (b->refCount <= 0) + if (b->refCount.get() <= 0) return text; juce_wchar* const newText = createCopy (text, b->allocatedNumChars); @@ -10020,7 +10064,7 @@ public: { StringHolder* const b = bufferFromText (text); - if (b->refCount <= 0 && b->allocatedNumChars >= numChars) + if (b->refCount.get() <= 0 && b->allocatedNumChars >= numChars) return text; juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); @@ -10041,7 +10085,7 @@ public: dest [numChars] = 0; } - int refCount; + Atomic refCount; size_t allocatedNumChars; juce_wchar text[1]; @@ -10108,7 +10152,7 @@ String& String::operator= (const String& other) throw() { juce_wchar* const newText = other.text; StringHolder::retain (newText); - StringHolder::release (static_cast (Atomic::swapPointers ((void* volatile*) &text, newText))); + StringHolder::release (reinterpret_cast *> (&text)->exchange (newText)); return *this; } @@ -37723,7 +37767,7 @@ public: InternalTimerThread() : Thread ("Juce Timer"), firstTimer (0), - callbackNeeded (false) + callbackNeeded (0) { triggerAsyncUpdate(); } @@ -37766,13 +37810,13 @@ public: if (timeUntilFirstTimer <= 0) { - if (callbackNeeded.set (true)) + if (callbackNeeded.compareAndSetBool (1, 0)) { postMessage (new Message()); const uint32 messageDeliveryTimeout = now + 2000; - while (callbackNeeded.get()) + while (callbackNeeded.get() != 0) { wait (4); @@ -37814,7 +37858,7 @@ public: JUCE_CATCH_EXCEPTION } - callbackNeeded.set (false); + callbackNeeded.set (0); } void handleMessage (const Message&) @@ -37882,24 +37926,7 @@ private: static InternalTimerThread* instance; static CriticalSection lock; Timer* volatile firstTimer; - - class AtomicBool - { - public: - AtomicBool (const bool value) throw() : value (static_cast (value)) {} - ~AtomicBool() throw() {} - - bool get() const throw() { return value != 0; } - bool set (const bool newValue) { return Atomic::compareAndExchange (value, newValue ? 1 : 0, value) != 0; } - - private: - int32 value; - - AtomicBool (const AtomicBool&); - AtomicBool& operator= (const AtomicBool&); - }; - - AtomicBool callbackNeeded; + Atomic callbackNeeded; void addTimer (Timer* const t) throw() { @@ -56530,10 +56557,13 @@ int FileBrowserComponent::getNumSelectedFiles() const throw() const File FileBrowserComponent::getSelectedFile (int index) const throw() { + if ((flags & canSelectDirectories) != 0 && filenameBox->getText().isEmpty()) + return currentRoot; + if (! filenameBox->isReadOnly()) return currentRoot.getChildFile (filenameBox->getText()); - else - return chosenFiles[index]; + + return chosenFiles[index]; } bool FileBrowserComponent::currentFileIsValid() const @@ -56704,6 +56734,9 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) if (f.isDirectory()) { setRoot (f); + + if ((flags & canSelectDirectories) != 0) + filenameBox->setText (String::empty); } else { @@ -56997,8 +57030,13 @@ bool FileChooser::showDialog (const bool selectsDirectories, flags |= FileBrowserComponent::canSelectFiles; if (selectsDirectories) + { flags |= FileBrowserComponent::canSelectDirectories; + if (! isSave) + flags |= FileBrowserComponent::filenameBoxIsReadOnly; + } + if (selectMultipleFiles) flags |= FileBrowserComponent::canSelectMultipleItems; @@ -69405,13 +69443,13 @@ public: SharedCursorHandle* retain() throw() { - Atomic::increment (refCount); + ++refCount; return this; } void release() { - if (Atomic::decrementAndReturn (refCount) == 0) + if (--refCount == 0) { if (isStandard) { @@ -69429,7 +69467,7 @@ public: private: void* const handle; - int32 refCount; + Atomic refCount; const MouseCursor::StandardCursorType standardType; const bool isStandard; @@ -211074,15 +211112,24 @@ const String SystemStats::getFullUserName() #if ! JUCE_USE_INTRINSICS // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in // older ones we have to actually call the ops as win32 functions.. -void Atomic::increment (int32& variable) { InterlockedIncrement (reinterpret_cast (&variable)); } -int32 Atomic::incrementAndReturn (int32& variable) { return InterlockedIncrement (reinterpret_cast (&variable)); } -void Atomic::decrement (int32& variable) { InterlockedDecrement (reinterpret_cast (&variable)); } -int32 Atomic::decrementAndReturn (int32& variable) { return InterlockedDecrement (reinterpret_cast (&variable)); } -int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return InterlockedCompareExchange (reinterpret_cast (&destination), newValue, oldValue); } -#endif +long juce_InterlockedExchange (volatile long* a, long b) throw() { return InterlockedExchange (a, b); } +long juce_InterlockedIncrement (volatile long* a) throw() { return InterlockedIncrement (a); } +long juce_InterlockedDecrement (volatile long* a) throw() { return InterlockedDecrement (a); } +long juce_InterlockedExchangeAdd (volatile long* a, long b) throw() { return InterlockedExchangeAdd (a, b); } +long juce_InterlockedCompareExchange (volatile long* a, long b, long c) throw() { return InterlockedCompareExchange (a, b, c); } + +__int64 juce_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) throw() +{ + jassertfalse; // This operation isn't available in old MS compiler versions! -void* Atomic::swapPointers (void* volatile* value1, void* volatile value2) { return InterlockedExchangePointer (value1, value2); } + __int64 oldValue = *value; + if (oldValue == valueToCompare) + *value = newValue; + + return oldValue; +} + +#endif CriticalSection::CriticalSection() throw() { @@ -212588,7 +212635,7 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool l }; ASTAT astat; - zerostruct (astat); + zeromem (&astat, sizeof (astat)); // (can't use zerostruct here in VC6) LANA_ENUM enums; zerostruct (enums); diff --git a/juce_amalgamated.h b/juce_amalgamated.h index b76274e3ec..23609b6c6a 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -3120,108 +3120,231 @@ private: #ifndef __JUCE_ATOMIC_JUCEHEADER__ #define __JUCE_ATOMIC_JUCEHEADER__ -class JUCE_API Atomic +template +class Atomic { public: - static void increment (int32& variable); + inline Atomic() throw() + : value (0) + { + } - static int32 incrementAndReturn (int32& variable); + inline Atomic (const Type initialValue) throw() + : value (initialValue) + { + } - static void decrement (int32& variable); + inline Atomic (const Atomic& other) throw() + : value (other.get()) + { + } - static int32 decrementAndReturn (int32& variable); + inline Atomic& operator= (const Atomic& other) throw() + { + set (other.get()); + } - static int32 compareAndExchange (int32& destination, int32 newValue, int32 requiredCurrentValue); + inline ~Atomic() throw() + { + // This class can only be used for types which are 32 or 64 bits in size. + static_jassert (sizeof (Type) == 4 || sizeof (Type) == 8); + } - static void* swapPointers (void* volatile* value1, void* value2); + Type get() const throw(); -private: - Atomic(); - Atomic (const Atomic&); - Atomic& operator= (const Atomic&); + void set (Type newValue) throw(); + + Type exchange (Type value) throw(); + + Type operator+= (Type amountToAdd) throw(); + + Type operator-= (Type amountToSubtract) throw(); + + Type operator++() throw(); + + Type operator--() throw(); + + bool compareAndSetBool (Type newValue, Type valueToCompare) throw(); + + Type compareAndSetValue (Type newValue, Type valueToCompare) throw(); + + static void memoryBarrier() throw(); + + #if JUCE_MSVC + __declspec (align (8)) + #else + __attribute__ ((aligned (8))) + #endif + + Type value; }; #if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \ - || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) // Older OSX builds using gcc4.1 or earlier... + || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) + #define JUCE_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier - inline void Atomic::increment (int32& variable) { OSAtomicIncrement32 (static_cast (&variable)); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast (&variable)); } - inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 (static_cast (&variable)); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 (static_cast (&variable)); } +#elif JUCE_GCC + #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { - for (;;) // Annoying workaround for OSX only having a bool CAS operation.. - { - if (OSAtomicCompareAndSwap32Barrier (oldValue, newValue, static_cast (&destination))) - return oldValue; +#else + #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics + + #if JUCE_USE_INTRINSICS + #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \ + _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier) + #define juce_InterlockedExchange(a, b) _InterlockedExchange(a, b) + #define juce_InterlockedIncrement(a) _InterlockedIncrement(a) + #define juce_InterlockedDecrement(a) _InterlockedDecrement(a) + #define juce_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b) + #define juce_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c) + #define juce_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c) + #define juce_MemoryBarrier MemoryBarrier + #else + // (these are defined in juce_win32_Threads.cpp) + long juce_InterlockedExchange (volatile long* a, long b) throw(); + long juce_InterlockedIncrement (volatile long* a) throw(); + long juce_InterlockedDecrement (volatile long* a) throw(); + long juce_InterlockedExchangeAdd (volatile long* a, long b) throw(); + long juce_InterlockedCompareExchange (volatile long* a, long b, long c) throw(); + __int64 juce_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) throw(); + static void juce_MemoryBarrier() throw() { long x = 0; juce_InterlockedIncrement (&x); } + #endif - const uint32 result = destination; - if (result != oldValue) - return result; - } - } + #if JUCE_64BIT + #pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64) + #define juce_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b) + #define juce_InterlockedExchange64(a, b) _InterlockedExchange64(a, b) + #define juce_InterlockedIncrement64(a) _InterlockedIncrement64(a) + #define juce_InterlockedDecrement64(a) _InterlockedDecrement64(a) + #else + // None of these atomics are available in a 32-bit Windows build!! + static __int64 juce_InterlockedExchangeAdd64 (volatile __int64* a, __int64 b) throw() { jassertfalse; __int64 old = *a; *a += b; return old; } + static __int64 juce_InterlockedExchange64 (volatile __int64* a, __int64 b) throw() { jassertfalse; __int64 old = *a; *a = b; return old; } + static __int64 juce_InterlockedIncrement64 (volatile __int64* a) throw() { jassertfalse; return ++*a; } + static __int64 juce_InterlockedDecrement64 (volatile __int64* a) throw() { jassertfalse; return --*a; } + #endif +#endif - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) - { - void* currentVal = *value1; - #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 && ! JUCE_64BIT - while (! OSAtomicCompareAndSwap32 (reinterpret_cast (currentVal), reinterpret_cast (value2), - const_cast (reinterpret_cast (value1)))) { currentVal = *value1; } - #else - while (! OSAtomicCompareAndSwapPtr (currentVal, value2, value1)) { currentVal = *value1; } - #endif - return currentVal; - } +template +inline Type Atomic::get() const throw() +{ + return const_cast *> (this)->operator+= (0); +} -#elif JUCE_LINUX && __INTEL_COMPILER // Linux with Intel compiler... +template +inline void Atomic::set (const Type newValue) throw() +{ + exchange (newValue); +} - inline void Atomic::increment (int32& variable) { _InterlockedIncrement (&variable); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (&variable); } - inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (&variable); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (&variable); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return _InterlockedCompareExchange (&destination, newValue, oldValue); } +template +Type Atomic::exchange (const Type newValue) throw() +{ + #if JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC + Type currentVal = value; + while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; } + return currentVal; + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedExchange ((volatile long*) &value, (long) newValue) + : (Type) juce_InterlockedExchange64 ((volatile __int64*) &value, (__int64) newValue); + #endif +} - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) - { - #if __ia64__ - return reinterpret_cast (_InterlockedExchange64 (const_cast (value1), reinterpret_cast<__int64> (value2))); - #else - return reinterpret_cast (_InterlockedExchange (const_cast (value1), reinterpret_cast (value2))); - #endif - } +template +inline Type Atomic::operator+= (const Type amountToAdd) throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicAdd32 ((int32_t) amountToAdd, (int32_t*) &value) + : (Type) OSAtomicAdd64 ((int64_t) amountToAdd, (int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) + : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, amountToAdd); + #endif +} + +template +inline Type Atomic::operator-= (const Type amountToSubtract) throw() +{ + return operator+= (sizeof (Type) == 4 ? (Type) (-(int32) amountToSubtract) + : (Type) (-(int64) amountToSubtract)); +} + +template +inline Type Atomic::operator++() throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32 ((int32_t*) &value) + : (Type) OSAtomicIncrement64 ((int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) + : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, 1); + #endif +} -#elif JUCE_GCC // On GCC, use intrinsics... +template +inline Type Atomic::operator--() throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32 ((int32_t*) &value) + : (Type) OSAtomicDecrement64 ((int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) + : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, -1); + #endif +} - inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } - inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } +template +inline bool Atomic::compareAndSetBool (const Type newValue, const Type valueToCompare) throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicCompareAndSwap32Barrier ((int32_t) valueToCompare, (int32_t) newValue, (int32_t*) &value) + : (Type) OSAtomicCompareAndSwap64Barrier ((int64_t) valueToCompare, (int64_t) newValue, (int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return compareAndSetValue (newValue, valueToCompare) == valueToCompare; + #elif JUCE_ATOMICS_GCC + return __sync_bool_compare_and_swap (&value, valueToCompare, newValue); + #endif +} - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) +template +inline Type Atomic::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() +{ + #if JUCE_ATOMICS_MAC + for (;;) // Annoying workaround for OSX only having a bool CAS operation.. { - void* currentVal = *value1; - while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } - return currentVal; - } + if (compareAndSetBool (newValue, valueToCompare)) + return valueToCompare; -#elif JUCE_USE_INTRINSICS // Windows... + const Type result = value; + if (result != valueToCompare) + return result; + } - // (If JUCE_USE_INTRINSICS isn't enabled, a fallback version of these methods is declared in juce_win32_Threads.cpp) - #pragma intrinsic (_InterlockedIncrement) - #pragma intrinsic (_InterlockedDecrement) - #pragma intrinsic (_InterlockedCompareExchange) + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedCompareExchange ((volatile long*) &value, (long) newValue, (long) valueToCompare) + : (Type) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) newValue, (__int64) valueToCompare); + #elif JUCE_ATOMICS_GCC + return __sync_val_compare_and_swap (&value, valueToCompare, newValue); + #endif +} - inline void Atomic::increment (int32& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } - inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return _InterlockedCompareExchange (reinterpret_cast (&destination), newValue, oldValue); } -#endif +template +inline void Atomic::memoryBarrier() throw() +{ + #if JUCE_ATOMICS_MAC + OSMemoryBarrier(); + #elif JUCE_ATOMICS_GCC + __sync_synchronize(); + #elif JUCE_ATOMICS_WINDOWS + juce_MemoryBarrier(); + #endif +} #endif // __JUCE_ATOMIC_JUCEHEADER__ /*** End of inlined file: juce_Atomic.h ***/ @@ -3232,40 +3355,37 @@ public: inline void incReferenceCount() throw() { - Atomic::increment (refCounts); - - jassert (refCounts > 0); + ++refCount; } inline void decReferenceCount() throw() { - jassert (refCounts > 0); + jassert (getReferenceCount() > 0); - if (Atomic::decrementAndReturn (refCounts) == 0) + if (--refCount == 0) delete this; } inline int getReferenceCount() const throw() { - return refCounts; + return refCount.get(); } protected: ReferenceCountedObject() - : refCounts (0) { } virtual ~ReferenceCountedObject() { // it's dangerous to delete an object that's still referenced by something else! - jassert (refCounts == 0); + jassert (getReferenceCount() == 0); } private: - int32 refCounts; + Atomic refCount; }; template @@ -7768,10 +7888,11 @@ private: bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly); + class Pimpl; + juce_UseDebuggingNewOperator private: - class Pimpl; friend class DirectoryIterator; friend class ScopedPointer; ScopedPointer pimpl; @@ -9386,6 +9507,7 @@ public: private: class SharedCursorHandle; + friend class SharedCursorHandle; SharedCursorHandle* cursorHandle; friend class MouseInputSourceInternal; diff --git a/src/containers/juce_ReferenceCountedObject.h b/src/containers/juce_ReferenceCountedObject.h index 94408a9e64..bf423b8dc2 100644 --- a/src/containers/juce_ReferenceCountedObject.h +++ b/src/containers/juce_ReferenceCountedObject.h @@ -68,9 +68,7 @@ public: */ inline void incReferenceCount() throw() { - Atomic::increment (refCounts); - - jassert (refCounts > 0); + ++refCount; } /** Decreases the object's reference count. @@ -79,16 +77,16 @@ public: */ inline void decReferenceCount() throw() { - jassert (refCounts > 0); + jassert (getReferenceCount() > 0); - if (Atomic::decrementAndReturn (refCounts) == 0) + if (--refCount == 0) delete this; } /** Returns the object's current reference count. */ inline int getReferenceCount() const throw() { - return refCounts; + return refCount.get(); } @@ -96,7 +94,6 @@ protected: //============================================================================== /** Creates the reference-counted object (with an initial ref count of zero). */ ReferenceCountedObject() - : refCounts (0) { } @@ -104,12 +101,12 @@ protected: virtual ~ReferenceCountedObject() { // it's dangerous to delete an object that's still referenced by something else! - jassert (refCounts == 0); + jassert (getReferenceCount() == 0); } private: //============================================================================== - int32 refCounts; + Atomic refCount; }; diff --git a/src/core/juce_Atomic.h b/src/core/juce_Atomic.h index 3c8340cf4d..9ef71b0466 100644 --- a/src/core/juce_Atomic.h +++ b/src/core/juce_Atomic.h @@ -28,123 +28,300 @@ //============================================================================== -/** Contains static functions for thread-safe atomic operations. +/** + Simple class to hold a primitive value and perform atomic operations on it. + + The type used must be a 32 or 64 bit primitive, like an int, pointer, etc. + There are methods to perform most of the basic atomic operations. */ -class JUCE_API Atomic +template +class Atomic { public: - /** Increments an integer in a thread-safe way. */ - static void increment (int32& variable); + /** Creates a new value, initialised to zero. */ + inline Atomic() throw() + : value (0) + { + } - /** Increments an integer in a thread-safe way and returns its new value. */ - static int32 incrementAndReturn (int32& variable); + /** Creates a new value, with a given initial value. */ + inline Atomic (const Type initialValue) throw() + : value (initialValue) + { + } - /** Decrements an integer in a thread-safe way. */ - static void decrement (int32& variable); + /** Copies another value (atomically). */ + inline Atomic (const Atomic& other) throw() + : value (other.get()) + { + } - /** Decrements an integer in a thread-safe way and returns its new value. */ - static int32 decrementAndReturn (int32& variable); + /** Copies another value onto this one (atomically). */ + inline Atomic& operator= (const Atomic& other) throw() + { + set (other.get()); + } - /** If the current value of destination is equal to requiredCurrentValue, this - will set it to newValue; otherwise, it will leave it unchanged. - @returns the original value of destination - */ - static int32 compareAndExchange (int32& destination, int32 newValue, int32 requiredCurrentValue); + /** Destructor. */ + inline ~Atomic() throw() + { + // This class can only be used for types which are 32 or 64 bits in size. + static_jassert (sizeof (Type) == 4 || sizeof (Type) == 8); + } - /** This atomically sets *value1 to be value2, and returns the previous value of *value1. */ - static void* swapPointers (void* volatile* value1, void* value2); + /** Atomically reads and returns the current value. */ + Type get() const throw(); -private: - Atomic(); - Atomic (const Atomic&); - Atomic& operator= (const Atomic&); -}; + /** Atomically sets the current value. */ + void set (Type newValue) throw(); + /** Atomically sets the current value, returning the value that was replaced. */ + Type exchange (Type value) throw(); -//============================================================================== -#if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \ - || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) // Older OSX builds using gcc4.1 or earlier... + /** Atomically adds a number to this value, returning the new value. */ + Type operator+= (Type amountToAdd) throw(); - inline void Atomic::increment (int32& variable) { OSAtomicIncrement32 (static_cast (&variable)); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast (&variable)); } - inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 (static_cast (&variable)); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 (static_cast (&variable)); } + /** Atomically subtracts a number from this value, returning the new value. */ + Type operator-= (Type amountToSubtract) throw(); - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { - for (;;) // Annoying workaround for OSX only having a bool CAS operation.. + /** Atomically increments this value, returning the new value. */ + Type operator++() throw(); + + /** Atomically decrements this value, returning the new value. */ + Type operator--() throw(); + + /** Atomically compares this value with a target value, and if it is equal, sets + this to be equal to a new value. + + This operation is the atomic equivalent of doing this: + @code + bool compareAndSetBool (Type newValue, Type valueToCompare) throw(); { - if (OSAtomicCompareAndSwap32Barrier (oldValue, newValue, static_cast (&destination))) - return oldValue; + if (get() == valueToCompare) + { + set (newValue); + return true; + } - const uint32 result = destination; - if (result != oldValue) - return result; + return false; } - } + @endcode - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) - { - void* currentVal = *value1; - #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 && ! JUCE_64BIT - while (! OSAtomicCompareAndSwap32 (reinterpret_cast (currentVal), reinterpret_cast (value2), - const_cast (reinterpret_cast (value1)))) { currentVal = *value1; } - #else - while (! OSAtomicCompareAndSwapPtr (currentVal, value2, value1)) { currentVal = *value1; } - #endif - return currentVal; - } + @returns true if the comparison was true and the value was replaced; false if + the comparison failed and the value was left unchanged. + @see compareAndSetValue + */ + bool compareAndSetBool (Type newValue, Type valueToCompare) throw(); -//============================================================================== -#elif JUCE_LINUX && __INTEL_COMPILER // Linux with Intel compiler... + /** Atomically compares this value with a target value, and if it is equal, sets + this to be equal to a new value. - inline void Atomic::increment (int32& variable) { _InterlockedIncrement (&variable); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (&variable); } - inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (&variable); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (&variable); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return _InterlockedCompareExchange (&destination, newValue, oldValue); } + This operation is the atomic equivalent of doing this: + @code + Type compareAndSetValue (Type newValue, Type valueToCompare) throw(); + { + Type oldValue = get(); + if (oldValue == valueToCompare) + set (newValue); + + return oldValue; + } + @endcode + + @returns the old value before it was changed. + @see compareAndSetBool + */ + Type compareAndSetValue (Type newValue, Type valueToCompare) throw(); + + /** Performs a memory write barrier. */ + static void memoryBarrier() throw(); + + //============================================================================== + #if JUCE_MSVC + __declspec (align (8)) + #else + __attribute__ ((aligned (8))) + #endif + + /** The raw value that this class operates on. + This is exposed publically in case you need to manipulate it directly + for performance reasons. + */ + Type value; +}; - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) - { - #if __ia64__ - return reinterpret_cast (_InterlockedExchange64 (const_cast (value1), reinterpret_cast<__int64> (value2))); - #else - return reinterpret_cast (_InterlockedExchange (const_cast (value1), reinterpret_cast (value2))); - #endif - } //============================================================================== -#elif JUCE_GCC // On GCC, use intrinsics... +/* + The following code allows the atomics to be performed as inline functions where possible... +*/ +#if (JUCE_IPHONE && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_3_2 || ! defined (__IPHONE_3_2))) \ + || (JUCE_MAC && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))) + #define JUCE_ATOMICS_MAC 1 // Older OSX builds using gcc4.1 or earlier +//============================================================================== +#elif JUCE_GCC + #define JUCE_ATOMICS_GCC 1 // GCC with intrinsics +//============================================================================== +#else + #define JUCE_ATOMICS_WINDOWS 1 // Windows with intrinsics + + #if JUCE_USE_INTRINSICS + #pragma intrinsic (_InterlockedExchange, _InterlockedIncrement, _InterlockedDecrement, _InterlockedCompareExchange, \ + _InterlockedCompareExchange64, _InterlockedExchangeAdd, _ReadWriteBarrier) + #define juce_InterlockedExchange(a, b) _InterlockedExchange(a, b) + #define juce_InterlockedIncrement(a) _InterlockedIncrement(a) + #define juce_InterlockedDecrement(a) _InterlockedDecrement(a) + #define juce_InterlockedExchangeAdd(a, b) _InterlockedExchangeAdd(a, b) + #define juce_InterlockedCompareExchange(a, b, c) _InterlockedCompareExchange(a, b, c) + #define juce_InterlockedCompareExchange64(a, b, c) _InterlockedCompareExchange64(a, b, c) + #define juce_MemoryBarrier MemoryBarrier + #else + // (these are defined in juce_win32_Threads.cpp) + long juce_InterlockedExchange (volatile long* a, long b) throw(); + long juce_InterlockedIncrement (volatile long* a) throw(); + long juce_InterlockedDecrement (volatile long* a) throw(); + long juce_InterlockedExchangeAdd (volatile long* a, long b) throw(); + long juce_InterlockedCompareExchange (volatile long* a, long b, long c) throw(); + __int64 juce_InterlockedCompareExchange64 (volatile __int64* a, __int64 b, __int64 c) throw(); + static void juce_MemoryBarrier() throw() { long x = 0; juce_InterlockedIncrement (&x); } + #endif + + #if JUCE_64BIT + #pragma intrinsic (_InterlockedExchangeAdd64, _InterlockedExchange64, _InterlockedIncrement64, _InterlockedDecrement64) + #define juce_InterlockedExchangeAdd64(a, b) _InterlockedExchangeAdd64(a, b) + #define juce_InterlockedExchange64(a, b) _InterlockedExchange64(a, b) + #define juce_InterlockedIncrement64(a) _InterlockedIncrement64(a) + #define juce_InterlockedDecrement64(a) _InterlockedDecrement64(a) + #else + // None of these atomics are available in a 32-bit Windows build!! + static __int64 juce_InterlockedExchangeAdd64 (volatile __int64* a, __int64 b) throw() { jassertfalse; __int64 old = *a; *a += b; return old; } + static __int64 juce_InterlockedExchange64 (volatile __int64* a, __int64 b) throw() { jassertfalse; __int64 old = *a; *a = b; return old; } + static __int64 juce_InterlockedIncrement64 (volatile __int64* a) throw() { jassertfalse; return ++*a; } + static __int64 juce_InterlockedDecrement64 (volatile __int64* a) throw() { jassertfalse; return --*a; } + #endif +#endif + +//============================================================================== +template +inline Type Atomic::get() const throw() +{ + return const_cast *> (this)->operator+= (0); +} - inline void Atomic::increment (int32& variable) { __sync_add_and_fetch (&variable, 1); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, 1); } - inline void Atomic::decrement (int32& variable) { __sync_add_and_fetch (&variable, -1); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return __sync_add_and_fetch (&variable, -1); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return __sync_val_compare_and_swap (&destination, oldValue, newValue); } +template +inline void Atomic::set (const Type newValue) throw() +{ + exchange (newValue); +} + +template +Type Atomic::exchange (const Type newValue) throw() +{ + #if JUCE_ATOMICS_MAC || JUCE_ATOMICS_GCC + Type currentVal = value; + while (! compareAndSetBool (newValue, currentVal)) { currentVal = value; } + return currentVal; + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedExchange ((volatile long*) &value, (long) newValue) + : (Type) juce_InterlockedExchange64 ((volatile __int64*) &value, (__int64) newValue); + #endif +} + +template +inline Type Atomic::operator+= (const Type amountToAdd) throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicAdd32 ((int32_t) amountToAdd, (int32_t*) &value) + : (Type) OSAtomicAdd64 ((int64_t) amountToAdd, (int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) (juce_InterlockedExchangeAdd ((volatile long*) &value, (long) amountToAdd) + (long) amountToAdd) + : (Type) (juce_InterlockedExchangeAdd64 ((volatile __int64*) &value, (__int64) amountToAdd) + (__int64) amountToAdd); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, amountToAdd); + #endif +} + +template +inline Type Atomic::operator-= (const Type amountToSubtract) throw() +{ + return operator+= (sizeof (Type) == 4 ? (Type) (-(int32) amountToSubtract) + : (Type) (-(int64) amountToSubtract)); +} - inline void* Atomic::swapPointers (void* volatile* value1, void* value2) +template +inline Type Atomic::operator++() throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicIncrement32 ((int32_t*) &value) + : (Type) OSAtomicIncrement64 ((int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedIncrement ((volatile long*) &value) + : (Type) juce_InterlockedIncrement64 ((volatile __int64*) &value); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, 1); + #endif +} + +template +inline Type Atomic::operator--() throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicDecrement32 ((int32_t*) &value) + : (Type) OSAtomicDecrement64 ((int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedDecrement ((volatile long*) &value) + : (Type) juce_InterlockedDecrement64 ((volatile __int64*) &value); + #elif JUCE_ATOMICS_GCC + return (Type) __sync_add_and_fetch (&value, -1); + #endif +} + +template +inline bool Atomic::compareAndSetBool (const Type newValue, const Type valueToCompare) throw() +{ + #if JUCE_ATOMICS_MAC + return sizeof (Type) == 4 ? (Type) OSAtomicCompareAndSwap32Barrier ((int32_t) valueToCompare, (int32_t) newValue, (int32_t*) &value) + : (Type) OSAtomicCompareAndSwap64Barrier ((int64_t) valueToCompare, (int64_t) newValue, (int64_t*) &value); + #elif JUCE_ATOMICS_WINDOWS + return compareAndSetValue (newValue, valueToCompare) == valueToCompare; + #elif JUCE_ATOMICS_GCC + return __sync_bool_compare_and_swap (&value, valueToCompare, newValue); + #endif +} + +template +inline Type Atomic::compareAndSetValue (const Type newValue, const Type valueToCompare) throw() +{ + #if JUCE_ATOMICS_MAC + for (;;) // Annoying workaround for OSX only having a bool CAS operation.. { - void* currentVal = *value1; - while (! __sync_bool_compare_and_swap (value1, currentVal, value2)) { currentVal = *value1; } - return currentVal; + if (compareAndSetBool (newValue, valueToCompare)) + return valueToCompare; + + const Type result = value; + if (result != valueToCompare) + return result; } -//============================================================================== -#elif JUCE_USE_INTRINSICS // Windows... - - // (If JUCE_USE_INTRINSICS isn't enabled, a fallback version of these methods is declared in juce_win32_Threads.cpp) - #pragma intrinsic (_InterlockedIncrement) - #pragma intrinsic (_InterlockedDecrement) - #pragma intrinsic (_InterlockedCompareExchange) - - inline void Atomic::increment (int32& variable) { _InterlockedIncrement (reinterpret_cast (&variable)); } - inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (reinterpret_cast (&variable)); } - inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (reinterpret_cast (&variable)); } - inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (reinterpret_cast (&variable)); } - inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return _InterlockedCompareExchange (reinterpret_cast (&destination), newValue, oldValue); } -#endif + #elif JUCE_ATOMICS_WINDOWS + return sizeof (Type) == 4 ? (Type) juce_InterlockedCompareExchange ((volatile long*) &value, (long) newValue, (long) valueToCompare) + : (Type) juce_InterlockedCompareExchange64 ((volatile __int64*) &value, (__int64) newValue, (__int64) valueToCompare); + #elif JUCE_ATOMICS_GCC + return __sync_val_compare_and_swap (&value, valueToCompare, newValue); + #endif +} + +template +inline void Atomic::memoryBarrier() throw() +{ + #if JUCE_ATOMICS_MAC + OSMemoryBarrier(); + #elif JUCE_ATOMICS_GCC + __sync_synchronize(); + #elif JUCE_ATOMICS_WINDOWS + juce_MemoryBarrier(); + #endif +} + #endif // __JUCE_ATOMIC_JUCEHEADER__ diff --git a/src/core/juce_SystemStats.cpp b/src/core/juce_SystemStats.cpp index f03088532c..bae4a85779 100644 --- a/src/core/juce_SystemStats.cpp +++ b/src/core/juce_SystemStats.cpp @@ -70,6 +70,54 @@ const StringArray SystemStats::getMACAddressStrings() //============================================================================== static bool juceInitialisedNonGUI = false; +#if JUCE_DEBUG +template +static void juce_testAtomicType (Type) +{ + Atomic a; + a.set ((Type) 10); + a += (Type) 15; + a.memoryBarrier(); + a -= (Type) 5; + ++a; + ++a; + --a; + a.memoryBarrier(); + + /* These are some simple test cases to check the atomics - let me know + if any of these assertions fail on your system! + */ + jassert (a.get() == (Type) 21); + jassert (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21); + jassert (a.get() == (Type) 21); + jassert (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21); + jassert (a.get() == (Type) 101); + jassert (! a.compareAndSetBool ((Type) 300, (Type) 200)); + jassert (a.get() == (Type) 101); + jassert (a.compareAndSetBool ((Type) 200, a.get())); + jassert (a.get() == (Type) 200); + + jassert (a.exchange ((Type) 300) == (Type) 200); + jassert (a.get() == (Type) 300); +} + +static void juce_testAtomics() +{ + juce_testAtomicType ((int) 0); + juce_testAtomicType ((unsigned int) 0); + juce_testAtomicType ((int32) 0); + juce_testAtomicType ((uint32) 0); + juce_testAtomicType ((long) 0); + juce_testAtomicType ((void*) 0); + juce_testAtomicType ((int*) 0); + #if ! (JUCE_WINDOWS && JUCE_32BIT) // some 64-bit intrinsics aren't available on win32 + juce_testAtomicType ((int64) 0); + juce_testAtomicType ((uint64) 0); + #endif + +} +#endif + void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() { if (! juceInitialisedNonGUI) @@ -99,11 +147,7 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() int a2[3]; jassert (numElementsInArray(a2) == 3); - int n = 1; - Atomic::increment (n); - jassert (Atomic::incrementAndReturn (n) == 3); - Atomic::decrement (n); - jassert (Atomic::decrementAndReturn (n) == 1); + juce_testAtomics(); jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211); jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); diff --git a/src/events/juce_Timer.cpp b/src/events/juce_Timer.cpp index 7da04b1544..ee4e63785b 100644 --- a/src/events/juce_Timer.cpp +++ b/src/events/juce_Timer.cpp @@ -48,7 +48,7 @@ public: InternalTimerThread() : Thread ("Juce Timer"), firstTimer (0), - callbackNeeded (false) + callbackNeeded (0) { triggerAsyncUpdate(); } @@ -96,7 +96,7 @@ public: but if it fails it means the message-thread changed the value from under us so at least some processing is happenening and we can just loop around and try again */ - if (callbackNeeded.set (true)) + if (callbackNeeded.compareAndSetBool (1, 0)) { postMessage (new Message()); @@ -106,7 +106,7 @@ public: */ const uint32 messageDeliveryTimeout = now + 2000; - while (callbackNeeded.get()) + while (callbackNeeded.get() != 0) { wait (4); @@ -154,7 +154,7 @@ public: get a message then the value is true and the other thread can only set it to true again and we will get another callback to set it to false. */ - callbackNeeded.set (false); + callbackNeeded.set (0); } void handleMessage (const Message&) @@ -222,25 +222,7 @@ private: static InternalTimerThread* instance; static CriticalSection lock; Timer* volatile firstTimer; - - //============================================================================== - class AtomicBool - { - public: - AtomicBool (const bool value) throw() : value (static_cast (value)) {} - ~AtomicBool() throw() {} - - bool get() const throw() { return value != 0; } - bool set (const bool newValue) { return Atomic::compareAndExchange (value, newValue ? 1 : 0, value) != 0; } - - private: - int32 value; - - AtomicBool (const AtomicBool&); - AtomicBool& operator= (const AtomicBool&); - }; - - AtomicBool callbackNeeded; + Atomic callbackNeeded; //============================================================================== void addTimer (Timer* const t) throw() diff --git a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp index abf1d46975..623a97401a 100644 --- a/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp +++ b/src/gui/components/filebrowser/juce_FileBrowserComponent.cpp @@ -176,10 +176,13 @@ int FileBrowserComponent::getNumSelectedFiles() const throw() const File FileBrowserComponent::getSelectedFile (int index) const throw() { + if ((flags & canSelectDirectories) != 0 && filenameBox->getText().isEmpty()) + return currentRoot; + if (! filenameBox->isReadOnly()) return currentRoot.getChildFile (filenameBox->getText()); - else - return chosenFiles[index]; + + return chosenFiles[index]; } bool FileBrowserComponent::currentFileIsValid() const @@ -354,6 +357,9 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) if (f.isDirectory()) { setRoot (f); + + if ((flags & canSelectDirectories) != 0) + filenameBox->setText (String::empty); } else { diff --git a/src/gui/components/filebrowser/juce_FileChooser.cpp b/src/gui/components/filebrowser/juce_FileChooser.cpp index 411fd3cee2..3ebb54cc07 100644 --- a/src/gui/components/filebrowser/juce_FileChooser.cpp +++ b/src/gui/components/filebrowser/juce_FileChooser.cpp @@ -137,8 +137,13 @@ bool FileChooser::showDialog (const bool selectsDirectories, flags |= FileBrowserComponent::canSelectFiles; if (selectsDirectories) + { flags |= FileBrowserComponent::canSelectDirectories; + if (! isSave) + flags |= FileBrowserComponent::filenameBoxIsReadOnly; + } + if (selectMultipleFiles) flags |= FileBrowserComponent::canSelectMultipleItems; diff --git a/src/gui/components/mouse/juce_MouseCursor.cpp b/src/gui/components/mouse/juce_MouseCursor.cpp index 3354eaf085..15234134ae 100644 --- a/src/gui/components/mouse/juce_MouseCursor.cpp +++ b/src/gui/components/mouse/juce_MouseCursor.cpp @@ -73,13 +73,13 @@ public: SharedCursorHandle* retain() throw() { - Atomic::increment (refCount); + ++refCount; return this; } void release() { - if (Atomic::decrementAndReturn (refCount) == 0) + if (--refCount == 0) { if (isStandard) { @@ -99,7 +99,7 @@ public: private: void* const handle; - int32 refCount; + Atomic refCount; const MouseCursor::StandardCursorType standardType; const bool isStandard; diff --git a/src/gui/components/mouse/juce_MouseCursor.h b/src/gui/components/mouse/juce_MouseCursor.h index c36ea62c97..89dd45eb8a 100644 --- a/src/gui/components/mouse/juce_MouseCursor.h +++ b/src/gui/components/mouse/juce_MouseCursor.h @@ -145,6 +145,7 @@ public: private: class SharedCursorHandle; + friend class SharedCursorHandle; SharedCursorHandle* cursorHandle; friend class MouseInputSourceInternal; diff --git a/src/io/files/juce_DirectoryIterator.h b/src/io/files/juce_DirectoryIterator.h index fcea05271e..75f57a7db5 100644 --- a/src/io/files/juce_DirectoryIterator.h +++ b/src/io/files/juce_DirectoryIterator.h @@ -128,10 +128,11 @@ private: bool* isDirectory, bool* isHidden, int64* fileSize, Time* modTime, Time* creationTime, bool* isReadOnly); + class Pimpl; + juce_UseDebuggingNewOperator private: - class Pimpl; friend class DirectoryIterator; friend class ScopedPointer; ScopedPointer pimpl; diff --git a/src/native/windows/juce_win32_Network.cpp b/src/native/windows/juce_win32_Network.cpp index a0ecd89b3f..60733276ab 100644 --- a/src/native/windows/juce_win32_Network.cpp +++ b/src/native/windows/juce_win32_Network.cpp @@ -352,7 +352,7 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool l }; ASTAT astat; - zerostruct (astat); + zeromem (&astat, sizeof (astat)); // (can't use zerostruct here in VC6) LANA_ENUM enums; zerostruct (enums); diff --git a/src/native/windows/juce_win32_Threads.cpp b/src/native/windows/juce_win32_Threads.cpp index d69373724e..ed1fa17a71 100644 --- a/src/native/windows/juce_win32_Threads.cpp +++ b/src/native/windows/juce_win32_Threads.cpp @@ -35,15 +35,24 @@ #if ! JUCE_USE_INTRINSICS // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in // older ones we have to actually call the ops as win32 functions.. -void Atomic::increment (int32& variable) { InterlockedIncrement (reinterpret_cast (&variable)); } -int32 Atomic::incrementAndReturn (int32& variable) { return InterlockedIncrement (reinterpret_cast (&variable)); } -void Atomic::decrement (int32& variable) { InterlockedDecrement (reinterpret_cast (&variable)); } -int32 Atomic::decrementAndReturn (int32& variable) { return InterlockedDecrement (reinterpret_cast (&variable)); } -int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) - { return InterlockedCompareExchange (reinterpret_cast (&destination), newValue, oldValue); } -#endif +long juce_InterlockedExchange (volatile long* a, long b) throw() { return InterlockedExchange (a, b); } +long juce_InterlockedIncrement (volatile long* a) throw() { return InterlockedIncrement (a); } +long juce_InterlockedDecrement (volatile long* a) throw() { return InterlockedDecrement (a); } +long juce_InterlockedExchangeAdd (volatile long* a, long b) throw() { return InterlockedExchangeAdd (a, b); } +long juce_InterlockedCompareExchange (volatile long* a, long b, long c) throw() { return InterlockedCompareExchange (a, b, c); } + +__int64 juce_InterlockedCompareExchange64 (volatile __int64* value, __int64 newValue, __int64 valueToCompare) throw() +{ + jassertfalse; // This operation isn't available in old MS compiler versions! + + __int64 oldValue = *value; + if (oldValue == valueToCompare) + *value = newValue; -void* Atomic::swapPointers (void* volatile* value1, void* volatile value2) { return InterlockedExchangePointer (value1, value2); } + return oldValue; +} + +#endif //============================================================================== CriticalSection::CriticalSection() throw() diff --git a/src/text/juce_String.cpp b/src/text/juce_String.cpp index 3e20c49e76..ce7c767f40 100644 --- a/src/text/juce_String.cpp +++ b/src/text/juce_String.cpp @@ -63,7 +63,7 @@ public: static juce_wchar* createUninitialised (const size_t numChars) { StringHolder* const s = reinterpret_cast (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); - s->refCount = 0; + s->refCount.value = 0; s->allocatedNumChars = numChars; return &(s->text[0]); } @@ -91,12 +91,12 @@ public: //============================================================================== static void retain (juce_wchar* const text) throw() { - Atomic::increment (bufferFromText (text)->refCount); + ++(bufferFromText (text)->refCount); } static inline void release (StringHolder* const b) throw() { - if (Atomic::decrementAndReturn (b->refCount) == -1 && b != &empty) + if (--(b->refCount) == -1 && b != &empty) delete[] reinterpret_cast (b); } @@ -110,7 +110,7 @@ public: { StringHolder* const b = bufferFromText (text); - if (b->refCount <= 0) + if (b->refCount.get() <= 0) return text; juce_wchar* const newText = createCopy (text, b->allocatedNumChars); @@ -123,7 +123,7 @@ public: { StringHolder* const b = bufferFromText (text); - if (b->refCount <= 0 && b->allocatedNumChars >= numChars) + if (b->refCount.get() <= 0 && b->allocatedNumChars >= numChars) return text; juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); @@ -145,7 +145,7 @@ public: } //============================================================================== - int refCount; + Atomic refCount; size_t allocatedNumChars; juce_wchar text[1]; @@ -214,7 +214,7 @@ String& String::operator= (const String& other) throw() { juce_wchar* const newText = other.text; StringHolder::retain (newText); - StringHolder::release (static_cast (Atomic::swapPointers ((void* volatile*) &text, newText))); + StringHolder::release (reinterpret_cast *> (&text)->exchange (newText)); return *this; }