| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\Jucer.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\Jucer.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -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()); | |||
| @@ -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); | |||
| @@ -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: <foo/bar.h> or normal quotes. | |||
| const String getIncludePathForFileInJuceFolder (const String& pathFromJuceFolder, const File& targetIncludeFile) const; | |||
| Array<RelativePath> juceWrapperFiles; | |||
| protected: | |||
| @@ -87,6 +90,7 @@ protected: | |||
| String name; | |||
| const RelativePath getJucePathFromTargetFolder() const; | |||
| const String getDefaultBuildsRootFolder() const { return "Builds/"; } | |||
| const Array<RelativePath> getVSTFilesRequired() const; | |||
| @@ -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; | |||
| @@ -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 <ResizeFrame*> (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 <LassoComponent <SelectedItems::ItemType> > lasso; | |||
| bool mouseDownResult, isDraggingClickedComp; | |||
| SelectedItems::ItemType mouseDownCompUID; | |||
| OwnedArray <ResizeFrame> resizers; | |||
| void updateMarkers (bool isX) | |||
| { | |||
| @@ -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)); | |||
| @@ -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); | |||
| } | |||
| @@ -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) | |||
| { | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\amalgamator.pdb" | |||
| SubSystem="1" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\amalgamator.pdb" | |||
| SubSystem="1" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | |||
| SubSystem="1" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | |||
| SubSystem="1" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -54,8 +54,6 @@ | |||
| GenerateDebugInformation="true" | |||
| ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | |||
| SubSystem="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -115,8 +113,6 @@ | |||
| GenerateManifest="false" | |||
| OptimizeReferences="2" | |||
| EnableCOMDATFolding="2" | |||
| RandomizedBaseAddress="1" | |||
| DataExecutionPrevention="0" | |||
| TargetMachine="1"/> | |||
| <Tool Name="VCALinkTool"/> | |||
| <Tool Name="VCManifestTool"/> | |||
| @@ -1444,6 +1444,54 @@ const StringArray SystemStats::getMACAddressStrings() | |||
| static bool juceInitialisedNonGUI = false; | |||
| #if JUCE_DEBUG | |||
| template <typename Type> | |||
| static void juce_testAtomicType (Type) | |||
| { | |||
| Atomic<Type> 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 <StringHolder*> (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 <char*> (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<int> 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 <juce_wchar*> (Atomic::swapPointers ((void* volatile*) &text, newText))); | |||
| StringHolder::release (reinterpret_cast <Atomic<juce_wchar*>*> (&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<int32> (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 <int> 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 <int> 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 <volatile long*> (&variable)); } | |||
| int32 Atomic::incrementAndReturn (int32& variable) { return InterlockedIncrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| void Atomic::decrement (int32& variable) { InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| int32 Atomic::decrementAndReturn (int32& variable) { return InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return InterlockedCompareExchange (reinterpret_cast <volatile long*> (&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); | |||
| @@ -3120,108 +3120,231 @@ private: | |||
| #ifndef __JUCE_ATOMIC_JUCEHEADER__ | |||
| #define __JUCE_ATOMIC_JUCEHEADER__ | |||
| class JUCE_API Atomic | |||
| template <typename Type> | |||
| 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 <int32_t*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 (static_cast <int32_t*> (&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 <int32_t*> (&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 <int32_t> (currentVal), reinterpret_cast <int32_t> (value2), | |||
| const_cast <int32_t*> (reinterpret_cast <volatile int32_t*> (value1)))) { currentVal = *value1; } | |||
| #else | |||
| while (! OSAtomicCompareAndSwapPtr (currentVal, value2, value1)) { currentVal = *value1; } | |||
| #endif | |||
| return currentVal; | |||
| } | |||
| template <typename Type> | |||
| inline Type Atomic<Type>::get() const throw() | |||
| { | |||
| return const_cast <Atomic<Type>*> (this)->operator+= (0); | |||
| } | |||
| #elif JUCE_LINUX && __INTEL_COMPILER // Linux with Intel compiler... | |||
| template <typename Type> | |||
| inline void Atomic<Type>::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 <typename Type> | |||
| Type Atomic<Type>::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<void*> (_InterlockedExchange64 (const_cast<void**> (value1), reinterpret_cast<__int64> (value2))); | |||
| #else | |||
| return reinterpret_cast<void*> (_InterlockedExchange (const_cast<void**> (value1), reinterpret_cast<long> (value2))); | |||
| #endif | |||
| } | |||
| template <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::operator-= (const Type amountToSubtract) throw() | |||
| { | |||
| return operator+= (sizeof (Type) == 4 ? (Type) (-(int32) amountToSubtract) | |||
| : (Type) (-(int64) amountToSubtract)); | |||
| } | |||
| template <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline bool Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <volatile long*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return _InterlockedCompareExchange (reinterpret_cast <volatile long*> (&destination), newValue, oldValue); } | |||
| #endif | |||
| template <typename Type> | |||
| inline void Atomic<Type>::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 <int> refCount; | |||
| }; | |||
| template <class ReferenceCountedObjectClass> | |||
| @@ -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<Pimpl>; | |||
| ScopedPointer<Pimpl> pimpl; | |||
| @@ -9386,6 +9507,7 @@ public: | |||
| private: | |||
| class SharedCursorHandle; | |||
| friend class SharedCursorHandle; | |||
| SharedCursorHandle* cursorHandle; | |||
| friend class MouseInputSourceInternal; | |||
| @@ -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 <int> refCount; | |||
| }; | |||
| @@ -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 <typename Type> | |||
| 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 <int32_t*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return OSAtomicIncrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline void Atomic::decrement (int32& variable) { OSAtomicDecrement32 (static_cast <int32_t*> (&variable)); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return OSAtomicDecrement32 (static_cast <int32_t*> (&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 <int32_t*> (&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 <int32_t> (currentVal), reinterpret_cast <int32_t> (value2), | |||
| const_cast <int32_t*> (reinterpret_cast <volatile int32_t*> (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<void*> (_InterlockedExchange64 (const_cast<void**> (value1), reinterpret_cast<__int64> (value2))); | |||
| #else | |||
| return reinterpret_cast<void*> (_InterlockedExchange (const_cast<void**> (value1), reinterpret_cast<long> (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 <typename Type> | |||
| inline Type Atomic<Type>::get() const throw() | |||
| { | |||
| return const_cast <Atomic<Type>*> (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 <typename Type> | |||
| inline void Atomic<Type>::set (const Type newValue) throw() | |||
| { | |||
| exchange (newValue); | |||
| } | |||
| template <typename Type> | |||
| Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <typename Type> | |||
| inline bool Atomic<Type>::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 <typename Type> | |||
| inline Type Atomic<Type>::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 <volatile long*> (&variable)); } | |||
| inline int32 Atomic::incrementAndReturn (int32& variable) { return _InterlockedIncrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline void Atomic::decrement (int32& variable) { _InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline int32 Atomic::decrementAndReturn (int32& variable) { return _InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| inline int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return _InterlockedCompareExchange (reinterpret_cast <volatile long*> (&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 <typename Type> | |||
| inline void Atomic<Type>::memoryBarrier() throw() | |||
| { | |||
| #if JUCE_ATOMICS_MAC | |||
| OSMemoryBarrier(); | |||
| #elif JUCE_ATOMICS_GCC | |||
| __sync_synchronize(); | |||
| #elif JUCE_ATOMICS_WINDOWS | |||
| juce_MemoryBarrier(); | |||
| #endif | |||
| } | |||
| #endif // __JUCE_ATOMIC_JUCEHEADER__ | |||
| @@ -70,6 +70,54 @@ const StringArray SystemStats::getMACAddressStrings() | |||
| //============================================================================== | |||
| static bool juceInitialisedNonGUI = false; | |||
| #if JUCE_DEBUG | |||
| template <typename Type> | |||
| static void juce_testAtomicType (Type) | |||
| { | |||
| Atomic<Type> 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); | |||
| @@ -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<int32> (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 <int> callbackNeeded; | |||
| //============================================================================== | |||
| void addTimer (Timer* const t) throw() | |||
| @@ -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 | |||
| { | |||
| @@ -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; | |||
| @@ -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 <int> refCount; | |||
| const MouseCursor::StandardCursorType standardType; | |||
| const bool isStandard; | |||
| @@ -145,6 +145,7 @@ public: | |||
| private: | |||
| class SharedCursorHandle; | |||
| friend class SharedCursorHandle; | |||
| SharedCursorHandle* cursorHandle; | |||
| friend class MouseInputSourceInternal; | |||
| @@ -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<Pimpl>; | |||
| ScopedPointer<Pimpl> pimpl; | |||
| @@ -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); | |||
| @@ -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 <volatile long*> (&variable)); } | |||
| int32 Atomic::incrementAndReturn (int32& variable) { return InterlockedIncrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| void Atomic::decrement (int32& variable) { InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| int32 Atomic::decrementAndReturn (int32& variable) { return InterlockedDecrement (reinterpret_cast <volatile long*> (&variable)); } | |||
| int32 Atomic::compareAndExchange (int32& destination, int32 newValue, int32 oldValue) | |||
| { return InterlockedCompareExchange (reinterpret_cast <volatile long*> (&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() | |||
| @@ -63,7 +63,7 @@ public: | |||
| static juce_wchar* createUninitialised (const size_t numChars) | |||
| { | |||
| StringHolder* const s = reinterpret_cast <StringHolder*> (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 <char*> (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<int> 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 <juce_wchar*> (Atomic::swapPointers ((void* volatile*) &text, newText))); | |||
| StringHolder::release (reinterpret_cast <Atomic<juce_wchar*>*> (&text)->exchange (newText)); | |||
| return *this; | |||
| } | |||