Get rid of postponed calculation of transformation.
Remove unused methods.
Add command OCC25545 to reproduce the bug with data races.
- Get rid of C++11 lambda construction
- make code compilable with no HAVE_TBB defined
- add test case bugs/fclasses/bug25545
#include <TCollection_HAsciiString.hxx>
#include <GeomFill_Trihedron.hxx>
#include <BRepOffsetAPI_MakePipe.hxx>
+#include <Standard_Atomic.hxx>
#include <Standard_Version.hxx>
#ifdef HAVE_TBB
-#include <Standard_Atomic.hxx>
#include <tbb/blocked_range.h>
#include <tbb/parallel_for.h>
return 0;
}
+//====================================================
+// Auxiliary functor class for the command OCC25545;
+// it gets access to a vertex with the given index and
+// checks that X coordinate of the point is equal to index;
+// if it is not so then a data race is reported.
+//====================================================
+struct OCC25545_Functor
+{
+ OCC25545_Functor(const std::vector<TopoDS_Shape>& theShapeVec)
+ : myShapeVec(&theShapeVec),
+ myIsRaceDetected(0)
+ {}
+
+ void operator()(size_t i) const
+ {
+ if (!myIsRaceDetected) {
+ const TopoDS_Vertex& aV = TopoDS::Vertex (myShapeVec->at(i));
+ gp_Pnt aP = BRep_Tool::Pnt (aV);
+ if (aP.X () != static_cast<double> (i)) {
+ Standard_Atomic_Increment(&myIsRaceDetected);
+ }
+ }
+ }
+
+ const std::vector<TopoDS_Shape>* myShapeVec;
+ mutable volatile int myIsRaceDetected;
+};
+
+//=======================================================================
+//function : OCC25545
+//purpose : Tests data race when concurrently accessing TopLoc_Location::Transformation()
+//=======================================================================
+#ifdef HAVE_TBB
+static Standard_Integer OCC25545 (Draw_Interpretor& di,
+ Standard_Integer,
+ const char **)
+{
+ // Place vertices in a vector, giving the i-th vertex the
+ // transformation that translates it on the vector (i,0,0) from the origin.
+ size_t n = 1000;
+ std::vector<TopoDS_Shape> aShapeVec (n);
+ std::vector<TopLoc_Location> aLocVec (n);
+ TopoDS_Shape aShape = BRepBuilderAPI_MakeVertex (gp::Origin ());
+ aShapeVec[0] = aShape;
+ for (size_t i = 1; i < n; ++i) {
+ gp_Trsf aT;
+ aT.SetTranslation (gp_Vec (1, 0, 0));
+ aLocVec[i] = aLocVec[i - 1] * aT;
+ aShapeVec[i] = aShape.Moved (aLocVec[i]);
+ }
+
+ // Evaluator function will access vertices geometry
+ // concurrently
+ OCC25545_Functor aFunc(aShapeVec);
+
+ //concurrently process
+ tbb::parallel_for (size_t (0), n, aFunc, tbb::simple_partitioner ());
+ QVERIFY (!aFunc.myIsRaceDetected);
+ return 0;
+}
+#else
+static Standard_Integer OCC25545 (Draw_Interpretor&,
+ Standard_Integer,
+ const char **argv)
+{
+ cout << "Test skipped: command " << argv[0] << " requires TBB library" << endl;
+ return 0;
+}
+#endif
+
//=======================================================================
//function : OCC25547
//purpose :
theCommands.Add ("OCC25348", "OCC25348", __FILE__, OCC25348, group);
theCommands.Add ("OCC25413", "OCC25413 shape", __FILE__, OCC25413, group);
theCommands.Add ("OCC25446", "OCC25446 res b1 b2 op", __FILE__, OCC25446, group);
+ theCommands.Add ("OCC25545",
+ "no args; tests data race when concurrently accessing \n"
+ "\t\tTopLoc_Location::Transformation()",
+ __FILE__, OCC25545, group);
theCommands.Add ("OCC25547", "OCC25547", __FILE__, OCC25547, group);
return;
}
gp
is
- pointer TrsfPtr to Trsf from gp;
class Datum3D;
private class ItemLocation;
uses
Datum3D from TopLoc,
- Trsf from gp,
- TrsfPtr from TopLoc
+ Trsf from gp
is
Create(D : Datum3D from TopLoc;
- P : Integer from Standard;
- fromTrsf : Boolean from Standard = Standard_False) returns ItemLocation from TopLoc;
+ P : Integer from Standard) returns ItemLocation from TopLoc;
---Purpose: Sets the elementary Datum to <D>
-- Sets the exponent to <P>
- Create(anOther : ItemLocation from TopLoc) returns ItemLocation from TopLoc;
-
- Assign(me : in out; anOther : ItemLocation from TopLoc) returns ItemLocation from TopLoc;
- ---C++: alias operator=
- ---C++: return &
-
- Destroy(me : in out);
- ---C++: alias ~
-
fields
- myDatum : Datum3D from TopLoc;
- myPower : Integer from Standard;
- myTrsf : TrsfPtr from TopLoc;
+ myDatum : Datum3D from TopLoc;
+ myPower : Integer from Standard;
+ myTrsf : Trsf from gp;
friends
- class Location from TopLoc
-
+ class Location from TopLoc,
+ class SListOfItemLocation from TopLoc
+
end ItemLocation;
TopLoc_ItemLocation::TopLoc_ItemLocation
(const Handle(TopLoc_Datum3D)& D,
- const Standard_Integer P,
-// const Standard_Boolean fromtrsf) :
- const Standard_Boolean ) :
+ const Standard_Integer P) :
myDatum(D),
myPower(P),
- myTrsf(NULL)
+ myTrsf (D->Transformation().Powered (P))
{
}
-
-
-TopLoc_ItemLocation::TopLoc_ItemLocation(const TopLoc_ItemLocation& anOther): myTrsf(NULL)
-{
- if (anOther.myTrsf != NULL) {
- myTrsf = new gp_Trsf;
- *myTrsf = *(anOther.myTrsf);
- }
- myDatum = anOther.myDatum;
- myPower = anOther.myPower;
-}
-
-TopLoc_ItemLocation& TopLoc_ItemLocation::Assign(const TopLoc_ItemLocation& anOther)
-{
- if (anOther.myTrsf == NULL) {
- if (myTrsf != NULL) delete myTrsf;
- myTrsf = NULL;
- }
- else if (myTrsf != anOther.myTrsf) {
- if (myTrsf == NULL) myTrsf = new gp_Trsf;
- *myTrsf = *(anOther.myTrsf);
- }
- myDatum = anOther.myDatum;
- myPower = anOther.myPower;
-
- return *this;
-}
-
-void TopLoc_ItemLocation::Destroy()
-{
- if (myTrsf != NULL) delete myTrsf;
- myTrsf = NULL;
-}
-
#include <TopLoc_SListOfItemLocation.hxx>
#include <TopLoc_ItemLocation.hxx>
#include <gp_Trsf.hxx>
-#include <TopLoc_TrsfPtr.hxx>
static const gp_Trsf TheIdentity;
-
-static Standard_Boolean IsInternalIdentity(const TopLoc_Location& loc)
-{
- if (loc.IsIdentity()) {
- return Standard_True;
- }
-// if (loc.FirstDatum()->Transformation().Form() == gp_Identity) {
-// return Standard_True;
-// }
- return Standard_False;
-}
-
//=======================================================================
//function : TopLoc_Location
//purpose : constructor Identity
const gp_Trsf& TopLoc_Location::Transformation() const
{
- if (IsInternalIdentity(*this))
+ if (IsIdentity())
return TheIdentity;
- else {
- if (myItems.Value().myTrsf == NULL) {
- TopLoc_ItemLocation *I = (TopLoc_ItemLocation*) (void*) &this->myItems.Value();
- // CLE
- if (I->myTrsf == NULL) I->myTrsf = new gp_Trsf;
- *(I->myTrsf) = I->myDatum->Transformation();
- I->myTrsf->Power(I->myPower);
- I->myTrsf->PreMultiply(NextLocation().Transformation());
- }
- return *(myItems.Value().myTrsf);
- }
+ else
+ return myItems.Value().myTrsf;
}
TopLoc_Location::operator gp_Trsf() const
TopLoc_Location TopLoc_Location::Powered (const Standard_Integer pwr) const
{
- if (IsInternalIdentity(*this)) return *this;
+ if (IsIdentity()) return *this;
if (pwr == 1) return *this;
if (pwr == 0) return TopLoc_Location();
is
Create(I : ItemLocation from TopLoc; aTail : SListOfItemLocation from TopLoc) returns SListNodeOfItemLocation from TopLoc;
---C++:inline
-
- Count(me) returns Integer;
- ---C++:inline
- ---C++: return &
Tail(me) returns SListOfItemLocation from TopLoc;
---C++:inline
-- SListOfItemLocation Iterator;
-- for (Iterator = S; Iterator.More(); Iterator.Next())
-- X = Iterator.Value();
- --
- -- Memory usage is automatically managed for SListOfItemLocations
- -- (using reference counts).
- ---Example:
- -- If S1 and S2 are SListOfItemLocations :
- -- if S1.Value() is X.
- --
- -- And the following is done :
- -- S2 = S1;
- -- S2.SetValue(Y);
- --
- -- S1.Value() becomes also Y. So SListOfItemLocation must be used
- -- with care. Mainly the SetValue() method is
- -- dangerous.
uses
SListNodeOfItemLocation from TopLoc,
is
Create returns SListOfItemLocation from TopLoc;
---Purpose: Creates an empty List.
+ ---C++: inline
Create(anItem : ItemLocation from TopLoc; aTail : SListOfItemLocation from TopLoc)
returns SListOfItemLocation from TopLoc;
Create(Other : SListOfItemLocation from TopLoc)
returns SListOfItemLocation from TopLoc;
---Purpose: Creates a list from an other one. The lists are shared.
+ ---C++: inline
Assign(me : in out; Other : SListOfItemLocation from TopLoc)
returns SListOfItemLocation from TopLoc
---Level: Public
---Purpose: Sets the list to be empty.
---C++: alias ~
+ ---C++: inline
is static;
Value(me) returns any ItemLocation from TopLoc
NoSuchObject from Standard
is static;
- ChangeValue(me : in out) returns any ItemLocation from TopLoc
- ---Level: Public
- ---Purpose: Returns the current value of the list. An error is
- -- raised if the list is empty. This value may be
- -- modified. A method modifying the value can be
- -- called. The value will be modified in the list.
- ---Example: AList.ChangeValue().Modify()
- ---C++: return &
- raises
- NoSuchObject from Standard
- is static;
-
- SetValue(me : in out; anItem : ItemLocation from TopLoc)
- ---Level: Public
- ---Purpose: Changes the current value in the list. An error is
- -- raised if the list is empty.
- raises
- NoSuchObject from Standard
- is static;
-
Tail(me) returns SListOfItemLocation from TopLoc
---Level: Public
---Purpose: Returns the current tail of the list. On an empty
---C++: return const &
is static;
- ChangeTail(me : in out) returns SListOfItemLocation from TopLoc
- ---Level: Public
- ---Purpose: Returns the current tail of the list. This tail
- -- may be modified. A method modifying the tail can
- -- be called. The tail will be modified in the list.
- ---Example: AList.ChangeTail().Modify()
- ---C++: return &
- is static;
-
- SetTail(me : in out; aList : SListOfItemLocation from TopLoc)
- ---Level: Public
- ---Purpose: Changes the current tail in the list. On an empty
- -- list SetTail is Assign.
- is static;
-
Construct(me : in out; anItem : ItemLocation from TopLoc)
---Level: Public
---Purpose: Replaces the list by a list with <anItem> as Value
---C++: inline
is static;
- Constructed(me; anItem : ItemLocation from TopLoc) returns SListOfItemLocation from TopLoc
- ---Level: Public
- ---Purpose: Returns a new list with <anItem> as Value an the
- -- list <me> as tail.
- ---C++: inline
- is static;
-
ToTail(me : in out)
---Level: Public
---Purpose: Replaces the list <me> by its tail.
---C++: inline
is static;
-
- Initialize(me : in out; aList : SListOfItemLocation from TopLoc)
- ---Level: Public
- ---Purpose: Sets the iterator to iterate on the content of
- -- <aList>. This is Assign().
- ---C++: inline
- is static;
More(me) returns Boolean
---Level: Public
//purpose :
//=======================================================================
-TopLoc_SListOfItemLocation::TopLoc_SListOfItemLocation()
-{}
-
-//=======================================================================
-//function : TopLoc_SListOfItemLocation
-//purpose :
-//=======================================================================
-
TopLoc_SListOfItemLocation::TopLoc_SListOfItemLocation(const TopLoc_ItemLocation& anItem,
const TopLoc_SListOfItemLocation& aTail) :
myNode(new TopLoc_SListNodeOfItemLocation(anItem,aTail))
-{}
-
-//=======================================================================
-//function : TopLoc_SListOfItemLocation
-//purpose :
-//=======================================================================
-
-TopLoc_SListOfItemLocation::TopLoc_SListOfItemLocation(const TopLoc_SListOfItemLocation& Other) :
- myNode(Other.myNode)
{
+ if (!myNode->Tail().IsEmpty()) {
+ const gp_Trsf& aT = myNode->Tail().Value().myTrsf;
+ myNode->Value().myTrsf.PreMultiply (aT);
+ }
}
//=======================================================================
return *this;
}
-//=======================================================================
-//function : Clear
-//purpose :
-//=======================================================================
-
-void TopLoc_SListOfItemLocation::Clear()
-{
- if (!myNode.IsNull()) {
- myNode.Nullify();
- }
-}
-
//=======================================================================
//function : Value
//purpose :
return myNode->Value();
}
-//=======================================================================
-//function : ChangeValue
-//purpose :
-//=======================================================================
-
-TopLoc_ItemLocation& TopLoc_SListOfItemLocation::ChangeValue()
-{
- Standard_NoSuchObject_Raise_if(myNode.IsNull(),"TopLoc_SListOfItemLocation::Value");
- return myNode->Value();
-}
-
-//=======================================================================
-//function : SetValue
-//purpose :
-//=======================================================================
-
-void TopLoc_SListOfItemLocation::SetValue(const TopLoc_ItemLocation& anItem)
-{
- Standard_NoSuchObject_Raise_if(myNode.IsNull(),"TopLoc_SListOfItemLocation::Value");
- myNode->Value() = anItem;
-}
-
//=======================================================================
//function : Tail
//purpose :
else
return *this;
}
-
-//=======================================================================
-//function : ChangeTail
-//purpose :
-//=======================================================================
-
-TopLoc_SListOfItemLocation& TopLoc_SListOfItemLocation::ChangeTail()
-{
- if (!myNode.IsNull())
- return myNode->Tail();
- else
- return *this;
-}
-
-//=======================================================================
-//function : SetTail
-//purpose :
-//=======================================================================
-
-void TopLoc_SListOfItemLocation::SetTail(const TopLoc_SListOfItemLocation& aList)
-{
- if (!myNode.IsNull())
- myNode->Tail() = aList;
- else
- Assign(aList);
-}
// commercial license or contractual agreement.
//=======================================================================
-//function : IsEmpty
+//function : TopLoc_SListOfItemLocation
//purpose :
//=======================================================================
-inline Standard_Boolean TopLoc_SListOfItemLocation::IsEmpty() const
-{
- return myNode.IsNull();
-}
+inline TopLoc_SListOfItemLocation::TopLoc_SListOfItemLocation()
+{}
//=======================================================================
-//function : Construct
+//function : TopLoc_SListOfItemLocation
//purpose :
//=======================================================================
+inline TopLoc_SListOfItemLocation::TopLoc_SListOfItemLocation(const TopLoc_SListOfItemLocation& Other) :
+ myNode(Other.myNode)
+{
+}
+
//=======================================================================
-//function : Construct
+//function : IsEmpty
//purpose :
//=======================================================================
-inline void TopLoc_SListOfItemLocation::Construct(const TopLoc_ItemLocation& anItem)
+inline Standard_Boolean TopLoc_SListOfItemLocation::IsEmpty() const
{
- Assign(TopLoc_SListOfItemLocation(anItem,*this));
+ return myNode.IsNull();
}
//=======================================================================
-//function : Constructed
+//function : Clear
//purpose :
//=======================================================================
-inline TopLoc_SListOfItemLocation TopLoc_SListOfItemLocation::Constructed(const TopLoc_ItemLocation& anItem) const
+inline void TopLoc_SListOfItemLocation::Clear()
{
- return TopLoc_SListOfItemLocation(anItem,*this);
+ if (!myNode.IsNull()) {
+ myNode.Nullify();
+ }
}
//=======================================================================
-//function : ToTail
+//function : Construct
//purpose :
//=======================================================================
-inline void TopLoc_SListOfItemLocation::ToTail()
+inline void TopLoc_SListOfItemLocation::Construct(const TopLoc_ItemLocation& anItem)
{
- Assign(Tail());
+ Assign(TopLoc_SListOfItemLocation(anItem,*this));
}
//=======================================================================
-//function : Initialize
+//function : ToTail
//purpose :
//=======================================================================
-inline void TopLoc_SListOfItemLocation::Initialize(const TopLoc_SListOfItemLocation& aList)
+inline void TopLoc_SListOfItemLocation::ToTail()
{
- Assign(aList);
+ Assign(Tail());
}
//=======================================================================
Power (me : in out; N : Integer) raises ConstructionError is static;
- Powered (me : in out; N : Integer) returns Trsf
+ Powered (me; N : Integer) returns Trsf
---C++: inline
--- Purpose :
-- Computes the following composition of transformations
return Tresult;
}
-inline gp_Trsf gp_Trsf::Powered (const Standard_Integer N)
+inline gp_Trsf gp_Trsf::Powered (const Standard_Integer N) const
{
gp_Trsf T = *this;
T.Power (N);
--- /dev/null
+puts "============"
+puts "OCC25545"
+puts "============"
+puts ""
+#######################################################################
+# TopLoc_Location::Transformation() provokes data races
+#######################################################################
+
+pload QAcommands
+
+OCC25545