| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\Jucer.pdb" | ProgramDatabaseFile=".\Debug\Jucer.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\Jucer.pdb" | ProgramDatabaseFile=".\Debug\Jucer.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -526,9 +526,7 @@ private: | |||||
| linker->setAttribute ("EnableCOMDATFolding", "2"); | 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()); | String extraLinkerOptions (getExtraLinkerFlags().toString()); | ||||
| @@ -115,6 +115,28 @@ const File ProjectExporter::getTargetFolder() const | |||||
| return project.resolveFilename (getTargetLocation().toString()); | 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 | const RelativePath ProjectExporter::getJucePathFromTargetFolder() const | ||||
| { | { | ||||
| RelativePath juceFolder (getJuceFolder().toString(), RelativePath::projectFolder); | RelativePath juceFolder (getJuceFolder().toString(), RelativePath::projectFolder); | ||||
| @@ -78,6 +78,9 @@ public: | |||||
| Value getExtraCompilerFlags() const { return getSetting ("extraCompilerFlags"); } | Value getExtraCompilerFlags() const { return getSetting ("extraCompilerFlags"); } | ||||
| Value getExtraLinkerFlags() const { return getSetting ("extraLinkerFlags"); } | 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; | Array<RelativePath> juceWrapperFiles; | ||||
| protected: | protected: | ||||
| @@ -87,6 +90,7 @@ protected: | |||||
| String name; | String name; | ||||
| const RelativePath getJucePathFromTargetFolder() const; | const RelativePath getJucePathFromTargetFolder() const; | ||||
| const String getDefaultBuildsRootFolder() const { return "Builds/"; } | const String getDefaultBuildsRootFolder() const { return "Builds/"; } | ||||
| const Array<RelativePath> getVSTFilesRequired() const; | const Array<RelativePath> getVSTFilesRequired() const; | ||||
| @@ -251,12 +251,7 @@ private: | |||||
| if (exporter != 0) | 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()); | guards.add (exporter->getOSTestMacro()); | ||||
| } | } | ||||
| } | } | ||||
| @@ -266,7 +261,7 @@ private: | |||||
| if (uniquePaths.size() == 1) | if (uniquePaths.size() == 1) | ||||
| { | { | ||||
| out << "#include " << paths[0].quoted() << newLine; | |||||
| out << "#include " << paths[0] << newLine; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -286,7 +281,7 @@ private: | |||||
| for (i = 0; i < paths.size(); ++i) | for (i = 0; i < paths.size(); ++i) | ||||
| { | { | ||||
| out << (i == 0 ? "#if " : "#elif ") << guards[i] << newLine | out << (i == 0 ? "#if " : "#elif ") << guards[i] << newLine | ||||
| << " #include " << paths[i].quoted() << newLine; | |||||
| << " #include " << paths[i] << newLine; | |||||
| } | } | ||||
| out << "#endif" << newLine; | out << "#endif" << newLine; | ||||
| @@ -386,6 +386,7 @@ public: | |||||
| markerRootY.removeListener (this); | markerRootY.removeListener (this); | ||||
| getSelection().removeChangeListener (this); | getSelection().removeChangeListener (this); | ||||
| resizers.clear(); | |||||
| deleteAllChildren(); | deleteAllChildren(); | ||||
| } | } | ||||
| @@ -497,6 +498,7 @@ public: | |||||
| void resized() | void resized() | ||||
| { | { | ||||
| updateMarkers(); | updateMarkers(); | ||||
| updateResizeFrames(); | |||||
| } | } | ||||
| void changeListenerCallback (void*) | void changeListenerCallback (void*) | ||||
| @@ -543,16 +545,19 @@ public: | |||||
| for (i = 0; i < num; ++i) | for (i = 0; i < num; ++i) | ||||
| requiredIds.add (selection.getSelectedItem(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) | if (state.isValid()) // (the id may be a marker) | ||||
| { | { | ||||
| ResizeFrame* frame = new ResizeFrame (canvas, requiredIds[i], state); | ResizeFrame* frame = new ResizeFrame (canvas, requiredIds[i], state); | ||||
| resizers.add (frame); | |||||
| addAndMakeVisible (frame); | addAndMakeVisible (frame); | ||||
| frame->updatePosition(); | frame->updatePosition(); | ||||
| } | } | ||||
| @@ -576,6 +582,7 @@ private: | |||||
| ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso; | ScopedPointer <LassoComponent <SelectedItems::ItemType> > lasso; | ||||
| bool mouseDownResult, isDraggingClickedComp; | bool mouseDownResult, isDraggingClickedComp; | ||||
| SelectedItems::ItemType mouseDownCompUID; | SelectedItems::ItemType mouseDownCompUID; | ||||
| OwnedArray <ResizeFrame> resizers; | |||||
| void updateMarkers (bool isX) | void updateMarkers (bool isX) | ||||
| { | { | ||||
| @@ -80,7 +80,7 @@ public: | |||||
| if (isDraggingLeftRight()) | if (isDraggingLeftRight()) | ||||
| { | { | ||||
| verticalSnapTargets.add (SnapLine (0, -100.0f, 10000.0f)); | 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())) | if (zone.isDraggingWholeObject() || (zone.isDraggingLeftEdge() && zone.isDraggingRightEdge())) | ||||
| verticalSnapTargets.add (SnapLine ((float) getCanvasWidth() / 2.0f, 0, 10000.0f)); | verticalSnapTargets.add (SnapLine ((float) getCanvasWidth() / 2.0f, 0, 10000.0f)); | ||||
| @@ -89,7 +89,7 @@ public: | |||||
| if (isDraggingUpDown()) | if (isDraggingUpDown()) | ||||
| { | { | ||||
| horizontalSnapTargets.add (SnapLine (0, -100.0f, 10000.0f)); | 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())) | if (zone.isDraggingWholeObject() || (zone.isDraggingTopEdge() && zone.isDraggingBottomEdge())) | ||||
| horizontalSnapTargets.add (SnapLine ((float) getCanvasHeight() / 2.0f, 0, 10000.0f)); | horizontalSnapTargets.add (SnapLine ((float) getCanvasHeight() / 2.0f, 0, 10000.0f)); | ||||
| @@ -206,12 +206,12 @@ private: | |||||
| return StoredSettings::getInstance()->swatchColours.size(); | return StoredSettings::getInstance()->swatchColours.size(); | ||||
| } | } | ||||
| const Colour getSwatchColour (const int index) const | |||||
| const Colour getSwatchColour (int index) const | |||||
| { | { | ||||
| return StoredSettings::getInstance()->swatchColours [index]; | 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); | StoredSettings::getInstance()->swatchColours.set (index, newColour); | ||||
| } | } | ||||
| @@ -40,10 +40,12 @@ public: | |||||
| ValueTree getMarker (int index) const { return group.getChild (index); } | ValueTree getMarker (int index) const { return group.getChild (index); } | ||||
| ValueTree getMarkerNamed (const String& name) const { return group.getChildWithProperty (getMarkerNameProperty(), name); } | ValueTree getMarkerNamed (const String& name) const { return group.getChildWithProperty (getMarkerNameProperty(), name); } | ||||
| bool contains (const ValueTree& markerState) const { return markerState.isAChildOf (group); } | 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(); } | const String getName (const ValueTree& markerState) const { return markerState [getMarkerNameProperty()].toString(); } | ||||
| Value getNameAsValue (const ValueTree& markerState) const { return markerState.getPropertyAsValue (getMarkerNameProperty(), getUndoManager()); } | 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) | void createMarker (const String& name, int position) | ||||
| { | { | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\amalgamator.pdb" | ProgramDatabaseFile=".\Debug\amalgamator.pdb" | ||||
| SubSystem="1" | SubSystem="1" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\amalgamator.pdb" | ProgramDatabaseFile=".\Debug\amalgamator.pdb" | ||||
| SubSystem="1" | SubSystem="1" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | ProgramDatabaseFile=".\Debug\Plugin Host.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | ProgramDatabaseFile=".\Debug\JuceDemoPlugin.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | ||||
| SubSystem="1" | SubSystem="1" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | ProgramDatabaseFile=".\Debug\BinaryBuilder.pdb" | ||||
| SubSystem="1" | SubSystem="1" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | ProgramDatabaseFile=".\Debug\HelloWorld.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -54,8 +54,6 @@ | |||||
| GenerateDebugInformation="true" | GenerateDebugInformation="true" | ||||
| ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | ProgramDatabaseFile=".\Debug\JuceDemo.pdb" | ||||
| SubSystem="2" | SubSystem="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -115,8 +113,6 @@ | |||||
| GenerateManifest="false" | GenerateManifest="false" | ||||
| OptimizeReferences="2" | OptimizeReferences="2" | ||||
| EnableCOMDATFolding="2" | EnableCOMDATFolding="2" | ||||
| RandomizedBaseAddress="1" | |||||
| DataExecutionPrevention="0" | |||||
| TargetMachine="1"/> | TargetMachine="1"/> | ||||
| <Tool Name="VCALinkTool"/> | <Tool Name="VCALinkTool"/> | ||||
| <Tool Name="VCManifestTool"/> | <Tool Name="VCManifestTool"/> | ||||
| @@ -1444,6 +1444,54 @@ const StringArray SystemStats::getMACAddressStrings() | |||||
| static bool juceInitialisedNonGUI = false; | 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() | void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() | ||||
| { | { | ||||
| if (! juceInitialisedNonGUI) | if (! juceInitialisedNonGUI) | ||||
| @@ -1473,11 +1521,7 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() | |||||
| int a2[3]; | int a2[3]; | ||||
| jassert (numElementsInArray(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 ((uint16) 0x1122) == 0x2211); | ||||
| jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | ||||
| @@ -9962,7 +10006,7 @@ public: | |||||
| static juce_wchar* createUninitialised (const size_t numChars) | static juce_wchar* createUninitialised (const size_t numChars) | ||||
| { | { | ||||
| StringHolder* const s = reinterpret_cast <StringHolder*> (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); | StringHolder* const s = reinterpret_cast <StringHolder*> (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); | ||||
| s->refCount = 0; | |||||
| s->refCount.value = 0; | |||||
| s->allocatedNumChars = numChars; | s->allocatedNumChars = numChars; | ||||
| return &(s->text[0]); | return &(s->text[0]); | ||||
| } | } | ||||
| @@ -9989,12 +10033,12 @@ public: | |||||
| static void retain (juce_wchar* const text) throw() | static void retain (juce_wchar* const text) throw() | ||||
| { | { | ||||
| Atomic::increment (bufferFromText (text)->refCount); | |||||
| ++(bufferFromText (text)->refCount); | |||||
| } | } | ||||
| static inline void release (StringHolder* const b) throw() | 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); | delete[] reinterpret_cast <char*> (b); | ||||
| } | } | ||||
| @@ -10007,7 +10051,7 @@ public: | |||||
| { | { | ||||
| StringHolder* const b = bufferFromText (text); | StringHolder* const b = bufferFromText (text); | ||||
| if (b->refCount <= 0) | |||||
| if (b->refCount.get() <= 0) | |||||
| return text; | return text; | ||||
| juce_wchar* const newText = createCopy (text, b->allocatedNumChars); | juce_wchar* const newText = createCopy (text, b->allocatedNumChars); | ||||
| @@ -10020,7 +10064,7 @@ public: | |||||
| { | { | ||||
| StringHolder* const b = bufferFromText (text); | StringHolder* const b = bufferFromText (text); | ||||
| if (b->refCount <= 0 && b->allocatedNumChars >= numChars) | |||||
| if (b->refCount.get() <= 0 && b->allocatedNumChars >= numChars) | |||||
| return text; | return text; | ||||
| juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); | juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); | ||||
| @@ -10041,7 +10085,7 @@ public: | |||||
| dest [numChars] = 0; | dest [numChars] = 0; | ||||
| } | } | ||||
| int refCount; | |||||
| Atomic<int> refCount; | |||||
| size_t allocatedNumChars; | size_t allocatedNumChars; | ||||
| juce_wchar text[1]; | juce_wchar text[1]; | ||||
| @@ -10108,7 +10152,7 @@ String& String::operator= (const String& other) throw() | |||||
| { | { | ||||
| juce_wchar* const newText = other.text; | juce_wchar* const newText = other.text; | ||||
| StringHolder::retain (newText); | 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; | return *this; | ||||
| } | } | ||||
| @@ -37723,7 +37767,7 @@ public: | |||||
| InternalTimerThread() | InternalTimerThread() | ||||
| : Thread ("Juce Timer"), | : Thread ("Juce Timer"), | ||||
| firstTimer (0), | firstTimer (0), | ||||
| callbackNeeded (false) | |||||
| callbackNeeded (0) | |||||
| { | { | ||||
| triggerAsyncUpdate(); | triggerAsyncUpdate(); | ||||
| } | } | ||||
| @@ -37766,13 +37810,13 @@ public: | |||||
| if (timeUntilFirstTimer <= 0) | if (timeUntilFirstTimer <= 0) | ||||
| { | { | ||||
| if (callbackNeeded.set (true)) | |||||
| if (callbackNeeded.compareAndSetBool (1, 0)) | |||||
| { | { | ||||
| postMessage (new Message()); | postMessage (new Message()); | ||||
| const uint32 messageDeliveryTimeout = now + 2000; | const uint32 messageDeliveryTimeout = now + 2000; | ||||
| while (callbackNeeded.get()) | |||||
| while (callbackNeeded.get() != 0) | |||||
| { | { | ||||
| wait (4); | wait (4); | ||||
| @@ -37814,7 +37858,7 @@ public: | |||||
| JUCE_CATCH_EXCEPTION | JUCE_CATCH_EXCEPTION | ||||
| } | } | ||||
| callbackNeeded.set (false); | |||||
| callbackNeeded.set (0); | |||||
| } | } | ||||
| void handleMessage (const Message&) | void handleMessage (const Message&) | ||||
| @@ -37882,24 +37926,7 @@ private: | |||||
| static InternalTimerThread* instance; | static InternalTimerThread* instance; | ||||
| static CriticalSection lock; | static CriticalSection lock; | ||||
| Timer* volatile firstTimer; | 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() | void addTimer (Timer* const t) throw() | ||||
| { | { | ||||
| @@ -56530,10 +56557,13 @@ int FileBrowserComponent::getNumSelectedFiles() const throw() | |||||
| const File FileBrowserComponent::getSelectedFile (int index) const throw() | const File FileBrowserComponent::getSelectedFile (int index) const throw() | ||||
| { | { | ||||
| if ((flags & canSelectDirectories) != 0 && filenameBox->getText().isEmpty()) | |||||
| return currentRoot; | |||||
| if (! filenameBox->isReadOnly()) | if (! filenameBox->isReadOnly()) | ||||
| return currentRoot.getChildFile (filenameBox->getText()); | return currentRoot.getChildFile (filenameBox->getText()); | ||||
| else | |||||
| return chosenFiles[index]; | |||||
| return chosenFiles[index]; | |||||
| } | } | ||||
| bool FileBrowserComponent::currentFileIsValid() const | bool FileBrowserComponent::currentFileIsValid() const | ||||
| @@ -56704,6 +56734,9 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) | |||||
| if (f.isDirectory()) | if (f.isDirectory()) | ||||
| { | { | ||||
| setRoot (f); | setRoot (f); | ||||
| if ((flags & canSelectDirectories) != 0) | |||||
| filenameBox->setText (String::empty); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -56997,8 +57030,13 @@ bool FileChooser::showDialog (const bool selectsDirectories, | |||||
| flags |= FileBrowserComponent::canSelectFiles; | flags |= FileBrowserComponent::canSelectFiles; | ||||
| if (selectsDirectories) | if (selectsDirectories) | ||||
| { | |||||
| flags |= FileBrowserComponent::canSelectDirectories; | flags |= FileBrowserComponent::canSelectDirectories; | ||||
| if (! isSave) | |||||
| flags |= FileBrowserComponent::filenameBoxIsReadOnly; | |||||
| } | |||||
| if (selectMultipleFiles) | if (selectMultipleFiles) | ||||
| flags |= FileBrowserComponent::canSelectMultipleItems; | flags |= FileBrowserComponent::canSelectMultipleItems; | ||||
| @@ -69405,13 +69443,13 @@ public: | |||||
| SharedCursorHandle* retain() throw() | SharedCursorHandle* retain() throw() | ||||
| { | { | ||||
| Atomic::increment (refCount); | |||||
| ++refCount; | |||||
| return this; | return this; | ||||
| } | } | ||||
| void release() | void release() | ||||
| { | { | ||||
| if (Atomic::decrementAndReturn (refCount) == 0) | |||||
| if (--refCount == 0) | |||||
| { | { | ||||
| if (isStandard) | if (isStandard) | ||||
| { | { | ||||
| @@ -69429,7 +69467,7 @@ public: | |||||
| private: | private: | ||||
| void* const handle; | void* const handle; | ||||
| int32 refCount; | |||||
| Atomic <int> refCount; | |||||
| const MouseCursor::StandardCursorType standardType; | const MouseCursor::StandardCursorType standardType; | ||||
| const bool isStandard; | const bool isStandard; | ||||
| @@ -211074,15 +211112,24 @@ const String SystemStats::getFullUserName() | |||||
| #if ! JUCE_USE_INTRINSICS | #if ! JUCE_USE_INTRINSICS | ||||
| // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in | // 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.. | // 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() | CriticalSection::CriticalSection() throw() | ||||
| { | { | ||||
| @@ -212588,7 +212635,7 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool l | |||||
| }; | }; | ||||
| ASTAT astat; | ASTAT astat; | ||||
| zerostruct (astat); | |||||
| zeromem (&astat, sizeof (astat)); // (can't use zerostruct here in VC6) | |||||
| LANA_ENUM enums; | LANA_ENUM enums; | ||||
| zerostruct (enums); | zerostruct (enums); | ||||
| @@ -3120,108 +3120,231 @@ private: | |||||
| #ifndef __JUCE_ATOMIC_JUCEHEADER__ | #ifndef __JUCE_ATOMIC_JUCEHEADER__ | ||||
| #define __JUCE_ATOMIC_JUCEHEADER__ | #define __JUCE_ATOMIC_JUCEHEADER__ | ||||
| class JUCE_API Atomic | |||||
| template <typename Type> | |||||
| class Atomic | |||||
| { | { | ||||
| public: | 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))) \ | #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__ | #endif // __JUCE_ATOMIC_JUCEHEADER__ | ||||
| /*** End of inlined file: juce_Atomic.h ***/ | /*** End of inlined file: juce_Atomic.h ***/ | ||||
| @@ -3232,40 +3355,37 @@ public: | |||||
| inline void incReferenceCount() throw() | inline void incReferenceCount() throw() | ||||
| { | { | ||||
| Atomic::increment (refCounts); | |||||
| jassert (refCounts > 0); | |||||
| ++refCount; | |||||
| } | } | ||||
| inline void decReferenceCount() throw() | inline void decReferenceCount() throw() | ||||
| { | { | ||||
| jassert (refCounts > 0); | |||||
| jassert (getReferenceCount() > 0); | |||||
| if (Atomic::decrementAndReturn (refCounts) == 0) | |||||
| if (--refCount == 0) | |||||
| delete this; | delete this; | ||||
| } | } | ||||
| inline int getReferenceCount() const throw() | inline int getReferenceCount() const throw() | ||||
| { | { | ||||
| return refCounts; | |||||
| return refCount.get(); | |||||
| } | } | ||||
| protected: | protected: | ||||
| ReferenceCountedObject() | ReferenceCountedObject() | ||||
| : refCounts (0) | |||||
| { | { | ||||
| } | } | ||||
| virtual ~ReferenceCountedObject() | virtual ~ReferenceCountedObject() | ||||
| { | { | ||||
| // it's dangerous to delete an object that's still referenced by something else! | // it's dangerous to delete an object that's still referenced by something else! | ||||
| jassert (refCounts == 0); | |||||
| jassert (getReferenceCount() == 0); | |||||
| } | } | ||||
| private: | private: | ||||
| int32 refCounts; | |||||
| Atomic <int> refCount; | |||||
| }; | }; | ||||
| template <class ReferenceCountedObjectClass> | template <class ReferenceCountedObjectClass> | ||||
| @@ -7768,10 +7888,11 @@ private: | |||||
| bool* isDirectory, bool* isHidden, int64* fileSize, | bool* isDirectory, bool* isHidden, int64* fileSize, | ||||
| Time* modTime, Time* creationTime, bool* isReadOnly); | Time* modTime, Time* creationTime, bool* isReadOnly); | ||||
| class Pimpl; | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| class Pimpl; | |||||
| friend class DirectoryIterator; | friend class DirectoryIterator; | ||||
| friend class ScopedPointer<Pimpl>; | friend class ScopedPointer<Pimpl>; | ||||
| ScopedPointer<Pimpl> pimpl; | ScopedPointer<Pimpl> pimpl; | ||||
| @@ -9386,6 +9507,7 @@ public: | |||||
| private: | private: | ||||
| class SharedCursorHandle; | class SharedCursorHandle; | ||||
| friend class SharedCursorHandle; | |||||
| SharedCursorHandle* cursorHandle; | SharedCursorHandle* cursorHandle; | ||||
| friend class MouseInputSourceInternal; | friend class MouseInputSourceInternal; | ||||
| @@ -68,9 +68,7 @@ public: | |||||
| */ | */ | ||||
| inline void incReferenceCount() throw() | inline void incReferenceCount() throw() | ||||
| { | { | ||||
| Atomic::increment (refCounts); | |||||
| jassert (refCounts > 0); | |||||
| ++refCount; | |||||
| } | } | ||||
| /** Decreases the object's reference count. | /** Decreases the object's reference count. | ||||
| @@ -79,16 +77,16 @@ public: | |||||
| */ | */ | ||||
| inline void decReferenceCount() throw() | inline void decReferenceCount() throw() | ||||
| { | { | ||||
| jassert (refCounts > 0); | |||||
| jassert (getReferenceCount() > 0); | |||||
| if (Atomic::decrementAndReturn (refCounts) == 0) | |||||
| if (--refCount == 0) | |||||
| delete this; | delete this; | ||||
| } | } | ||||
| /** Returns the object's current reference count. */ | /** Returns the object's current reference count. */ | ||||
| inline int getReferenceCount() const throw() | 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). */ | /** Creates the reference-counted object (with an initial ref count of zero). */ | ||||
| ReferenceCountedObject() | ReferenceCountedObject() | ||||
| : refCounts (0) | |||||
| { | { | ||||
| } | } | ||||
| @@ -104,12 +101,12 @@ protected: | |||||
| virtual ~ReferenceCountedObject() | virtual ~ReferenceCountedObject() | ||||
| { | { | ||||
| // it's dangerous to delete an object that's still referenced by something else! | // it's dangerous to delete an object that's still referenced by something else! | ||||
| jassert (refCounts == 0); | |||||
| jassert (getReferenceCount() == 0); | |||||
| } | } | ||||
| private: | 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: | 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__ | #endif // __JUCE_ATOMIC_JUCEHEADER__ | ||||
| @@ -70,6 +70,54 @@ const StringArray SystemStats::getMACAddressStrings() | |||||
| //============================================================================== | //============================================================================== | ||||
| static bool juceInitialisedNonGUI = false; | 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() | void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() | ||||
| { | { | ||||
| if (! juceInitialisedNonGUI) | if (! juceInitialisedNonGUI) | ||||
| @@ -99,11 +147,7 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI() | |||||
| int a2[3]; | int a2[3]; | ||||
| jassert (numElementsInArray(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 ((uint16) 0x1122) == 0x2211); | ||||
| jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211); | ||||
| @@ -48,7 +48,7 @@ public: | |||||
| InternalTimerThread() | InternalTimerThread() | ||||
| : Thread ("Juce Timer"), | : Thread ("Juce Timer"), | ||||
| firstTimer (0), | firstTimer (0), | ||||
| callbackNeeded (false) | |||||
| callbackNeeded (0) | |||||
| { | { | ||||
| triggerAsyncUpdate(); | triggerAsyncUpdate(); | ||||
| } | } | ||||
| @@ -96,7 +96,7 @@ public: | |||||
| but if it fails it means the message-thread changed the value from under us so at least | 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 | 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()); | postMessage (new Message()); | ||||
| @@ -106,7 +106,7 @@ public: | |||||
| */ | */ | ||||
| const uint32 messageDeliveryTimeout = now + 2000; | const uint32 messageDeliveryTimeout = now + 2000; | ||||
| while (callbackNeeded.get()) | |||||
| while (callbackNeeded.get() != 0) | |||||
| { | { | ||||
| wait (4); | 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 | 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. | we will get another callback to set it to false. | ||||
| */ | */ | ||||
| callbackNeeded.set (false); | |||||
| callbackNeeded.set (0); | |||||
| } | } | ||||
| void handleMessage (const Message&) | void handleMessage (const Message&) | ||||
| @@ -222,25 +222,7 @@ private: | |||||
| static InternalTimerThread* instance; | static InternalTimerThread* instance; | ||||
| static CriticalSection lock; | static CriticalSection lock; | ||||
| Timer* volatile firstTimer; | 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() | void addTimer (Timer* const t) throw() | ||||
| @@ -176,10 +176,13 @@ int FileBrowserComponent::getNumSelectedFiles() const throw() | |||||
| const File FileBrowserComponent::getSelectedFile (int index) const throw() | const File FileBrowserComponent::getSelectedFile (int index) const throw() | ||||
| { | { | ||||
| if ((flags & canSelectDirectories) != 0 && filenameBox->getText().isEmpty()) | |||||
| return currentRoot; | |||||
| if (! filenameBox->isReadOnly()) | if (! filenameBox->isReadOnly()) | ||||
| return currentRoot.getChildFile (filenameBox->getText()); | return currentRoot.getChildFile (filenameBox->getText()); | ||||
| else | |||||
| return chosenFiles[index]; | |||||
| return chosenFiles[index]; | |||||
| } | } | ||||
| bool FileBrowserComponent::currentFileIsValid() const | bool FileBrowserComponent::currentFileIsValid() const | ||||
| @@ -354,6 +357,9 @@ void FileBrowserComponent::fileDoubleClicked (const File& f) | |||||
| if (f.isDirectory()) | if (f.isDirectory()) | ||||
| { | { | ||||
| setRoot (f); | setRoot (f); | ||||
| if ((flags & canSelectDirectories) != 0) | |||||
| filenameBox->setText (String::empty); | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| @@ -137,8 +137,13 @@ bool FileChooser::showDialog (const bool selectsDirectories, | |||||
| flags |= FileBrowserComponent::canSelectFiles; | flags |= FileBrowserComponent::canSelectFiles; | ||||
| if (selectsDirectories) | if (selectsDirectories) | ||||
| { | |||||
| flags |= FileBrowserComponent::canSelectDirectories; | flags |= FileBrowserComponent::canSelectDirectories; | ||||
| if (! isSave) | |||||
| flags |= FileBrowserComponent::filenameBoxIsReadOnly; | |||||
| } | |||||
| if (selectMultipleFiles) | if (selectMultipleFiles) | ||||
| flags |= FileBrowserComponent::canSelectMultipleItems; | flags |= FileBrowserComponent::canSelectMultipleItems; | ||||
| @@ -73,13 +73,13 @@ public: | |||||
| SharedCursorHandle* retain() throw() | SharedCursorHandle* retain() throw() | ||||
| { | { | ||||
| Atomic::increment (refCount); | |||||
| ++refCount; | |||||
| return this; | return this; | ||||
| } | } | ||||
| void release() | void release() | ||||
| { | { | ||||
| if (Atomic::decrementAndReturn (refCount) == 0) | |||||
| if (--refCount == 0) | |||||
| { | { | ||||
| if (isStandard) | if (isStandard) | ||||
| { | { | ||||
| @@ -99,7 +99,7 @@ public: | |||||
| private: | private: | ||||
| void* const handle; | void* const handle; | ||||
| int32 refCount; | |||||
| Atomic <int> refCount; | |||||
| const MouseCursor::StandardCursorType standardType; | const MouseCursor::StandardCursorType standardType; | ||||
| const bool isStandard; | const bool isStandard; | ||||
| @@ -145,6 +145,7 @@ public: | |||||
| private: | private: | ||||
| class SharedCursorHandle; | class SharedCursorHandle; | ||||
| friend class SharedCursorHandle; | |||||
| SharedCursorHandle* cursorHandle; | SharedCursorHandle* cursorHandle; | ||||
| friend class MouseInputSourceInternal; | friend class MouseInputSourceInternal; | ||||
| @@ -128,10 +128,11 @@ private: | |||||
| bool* isDirectory, bool* isHidden, int64* fileSize, | bool* isDirectory, bool* isHidden, int64* fileSize, | ||||
| Time* modTime, Time* creationTime, bool* isReadOnly); | Time* modTime, Time* creationTime, bool* isReadOnly); | ||||
| class Pimpl; | |||||
| juce_UseDebuggingNewOperator | juce_UseDebuggingNewOperator | ||||
| private: | private: | ||||
| class Pimpl; | |||||
| friend class DirectoryIterator; | friend class DirectoryIterator; | ||||
| friend class ScopedPointer<Pimpl>; | friend class ScopedPointer<Pimpl>; | ||||
| ScopedPointer<Pimpl> pimpl; | ScopedPointer<Pimpl> pimpl; | ||||
| @@ -352,7 +352,7 @@ static int getMACAddressesViaNetBios (int64* addresses, int maxNum, const bool l | |||||
| }; | }; | ||||
| ASTAT astat; | ASTAT astat; | ||||
| zerostruct (astat); | |||||
| zeromem (&astat, sizeof (astat)); // (can't use zerostruct here in VC6) | |||||
| LANA_ENUM enums; | LANA_ENUM enums; | ||||
| zerostruct (enums); | zerostruct (enums); | ||||
| @@ -35,15 +35,24 @@ | |||||
| #if ! JUCE_USE_INTRINSICS | #if ! JUCE_USE_INTRINSICS | ||||
| // In newer compilers, the inline versions of these are used (in juce_Atomic.h), but in | // 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.. | // 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() | CriticalSection::CriticalSection() throw() | ||||
| @@ -63,7 +63,7 @@ public: | |||||
| static juce_wchar* createUninitialised (const size_t numChars) | static juce_wchar* createUninitialised (const size_t numChars) | ||||
| { | { | ||||
| StringHolder* const s = reinterpret_cast <StringHolder*> (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); | StringHolder* const s = reinterpret_cast <StringHolder*> (new char [sizeof (StringHolder) + numChars * sizeof (juce_wchar)]); | ||||
| s->refCount = 0; | |||||
| s->refCount.value = 0; | |||||
| s->allocatedNumChars = numChars; | s->allocatedNumChars = numChars; | ||||
| return &(s->text[0]); | return &(s->text[0]); | ||||
| } | } | ||||
| @@ -91,12 +91,12 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| static void retain (juce_wchar* const text) throw() | static void retain (juce_wchar* const text) throw() | ||||
| { | { | ||||
| Atomic::increment (bufferFromText (text)->refCount); | |||||
| ++(bufferFromText (text)->refCount); | |||||
| } | } | ||||
| static inline void release (StringHolder* const b) throw() | 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); | delete[] reinterpret_cast <char*> (b); | ||||
| } | } | ||||
| @@ -110,7 +110,7 @@ public: | |||||
| { | { | ||||
| StringHolder* const b = bufferFromText (text); | StringHolder* const b = bufferFromText (text); | ||||
| if (b->refCount <= 0) | |||||
| if (b->refCount.get() <= 0) | |||||
| return text; | return text; | ||||
| juce_wchar* const newText = createCopy (text, b->allocatedNumChars); | juce_wchar* const newText = createCopy (text, b->allocatedNumChars); | ||||
| @@ -123,7 +123,7 @@ public: | |||||
| { | { | ||||
| StringHolder* const b = bufferFromText (text); | StringHolder* const b = bufferFromText (text); | ||||
| if (b->refCount <= 0 && b->allocatedNumChars >= numChars) | |||||
| if (b->refCount.get() <= 0 && b->allocatedNumChars >= numChars) | |||||
| return text; | return text; | ||||
| juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); | juce_wchar* const newText = createUninitialised (jmax (b->allocatedNumChars, numChars)); | ||||
| @@ -145,7 +145,7 @@ public: | |||||
| } | } | ||||
| //============================================================================== | //============================================================================== | ||||
| int refCount; | |||||
| Atomic<int> refCount; | |||||
| size_t allocatedNumChars; | size_t allocatedNumChars; | ||||
| juce_wchar text[1]; | juce_wchar text[1]; | ||||
| @@ -214,7 +214,7 @@ String& String::operator= (const String& other) throw() | |||||
| { | { | ||||
| juce_wchar* const newText = other.text; | juce_wchar* const newText = other.text; | ||||
| StringHolder::retain (newText); | 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; | return *this; | ||||
| } | } | ||||