Added a concurrency-safe version of DT3::find_conflicts + better doc

This commit is contained in:
Clement Jamin 2013-06-05 17:23:19 +02:00
parent 62ba125fea
commit 440a654a58
7 changed files with 83 additions and 64 deletions

View File

@ -148,9 +148,9 @@ The optional argument `start` is used as a starting place for the search.
The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the insertion will
try to lock vertices/cells before modifying them. If it succeeds, *could_lock_zone
try to lock cells before modifying them. If it succeeds, *could_lock_zone
is true, otherwise it is false and the return value is Vertex_handle()
(the point is not inserted). In any case, the locked vertices are not unlocked by the
(the point is not inserted). In any case, the locked cells are not unlocked by the
function, leaving this choice to the user.
*/
Vertex_handle insert(const Point & p,
@ -259,9 +259,9 @@ void remove(Vertex_handle v);
Removes the vertex `v` from the triangulation.
This function is concurrency-safe if the triangulation is concurrency-safe. The removal will
try to lock vertices/cells before deleting/modifying them. If it succeeds, *could_lock_zone
try to lock cells before deleting/modifying them. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the point is not removed). In any case,
the locked vertices are not unlocked by the function, leaving this choice to the user.
the locked cells are not unlocked by the function, leaving this choice to the user.
This function will try to remove `v` only if the removal does not
decrease the dimension. If the removal would decrease dimension, the function returns false
@ -403,6 +403,12 @@ respectively in the output iterators:
(resp. edges) `(t, i)` where the cell (resp. facet) `t` is in
conflict, but `t->neighbor(i)` is not.
- `could_lock_zone`: The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the algorithm will
try to lock all the cells of the conflict zone. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the returned conflict zone is only partial). In any case,
the locked cells are not unlocked by the function, leaving this choice to the user.
This function can be used in conjunction with `insert_in_hole()` in order
to decide the insertion of a point after seeing which elements of the
triangulation are affected.
@ -415,7 +421,7 @@ class OutputIteratorCells>
std::pair<OutputIteratorBoundaryFacets, OutputIteratorCells>
find_conflicts(Point p, Cell_handle c,
OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit);
OutputIteratorCells cit, bool *could_lock_zone = NULL);
/*!
Same as the other `find_conflicts()` function, except that it also
@ -432,6 +438,12 @@ conflict, but `t->neighbor(i)` is not.
- `ifit`: the facets (resp. edges) inside the hole, that is, delimiting
two cells (resp facets) in conflict.
- `could_lock_zone`: The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the algorithm will
try to lock all the cells of the conflict zone. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the returned conflict zone is only partial). In any case,
the locked cells are not unlocked by the function, leaving this choice to the user.
Returns the `Triple` composed of the resulting output iterators.
\pre `dt`.`dimension()` \f$ \geq2\f$, and `c` is in conflict with `p`.
@ -445,7 +457,8 @@ OutputIteratorInternalFacets>
find_conflicts(Point p, Cell_handle c,
OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit,
OutputIteratorInternalFacets ifit);
OutputIteratorInternalFacets ifit,
bool *could_lock_zone = NULL);
/*!
This function is renamed `vertices_on_conflict_zone_boundary` since CGAL-3.8.

View File

@ -132,9 +132,9 @@ constructed handle.
The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the insertion will
try to lock vertices/cells before modifying them. If it succeeds, *could_lock_zone
try to lock cells before modifying them. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the point is not inserted). In any case,
the locked vertices are not unlocked by the function, leaving this choice to the user.
the locked cells are not unlocked by the function, leaving this choice to the user.
*/
Vertex_handle insert(const Weighted_point & p,
Cell_handle start = Cell_handle(), bool *could_lock_zone = NULL);
@ -239,9 +239,9 @@ void remove(Vertex_handle v);
Removes the vertex `v` from the triangulation.
This function is concurrency-safe if the triangulation is concurrency-safe. The removal will
try to lock vertices/cells before deleting/modifying them. If it succeeds, *could_lock_zone
try to lock cells before deleting/modifying them. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the point is not removed). In any case,
the locked vertices are not unlocked by the function, leaving this choice to the user.
the locked cells are not unlocked by the function, leaving this choice to the user.
This function will try to remove `v` only if the removal does not
decrease the dimension.
@ -425,17 +425,17 @@ Compute the conflicts with `p`.
@param cit The cells (resp. facets) in conflict with `p`.
@param bfit The facets (resp. edges) on the boundary of the conflict zone, that is, the facets (resp.\ edges) `(t, i)` where the cell (resp.. facet) `t` is in conflict, but `t->neighbor(i)` is not.
@param ifit The facets (resp.\ edges) inside the conflict zone, that facets incident to two cells (resp.\ facets) in conflict.
@param could_lock_zone The optional argument `could_lock_zone` is used by the concurrency-safe
@param could_lock_zone The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the algorithm will
try to lock vertices of the conflict zone. If it succeeds, *could_lock_zone
try to lock all the cells of the conflict zone. If it succeeds, *could_lock_zone
is true, otherwise it is false (and the returned conflict zone is only partial). In any case,
the locked vertices are not unlocked by the function, leaving this choice to the user.
@param p_this_facet_must_be_in_the_cz
If the optional argument `p_this_facet_must_be_in_the_cz` is not null, the algorithm will check
the locked cells are not unlocked by the function, leaving this choice to the user.
@param this_facet_must_be_in_the_cz
If the optional argument `this_facet_must_be_in_the_cz` is not null, the algorithm will check
if this facet is in the conflict zone (it may be internal as well as boundary).
@param p_the_facet_is_in_its_cz
This argument must be not null if the previous `p_this_facet_must_be_in_the_cz` argument is not null.
The boolean value pointed by this pointer is set to true if *`p_this_facet_must_be_in_the_cz` is
@param the_facet_is_in_its_cz
This argument must be not null if the previous `this_facet_must_be_in_the_cz` argument is not null.
The boolean value pointed by this pointer is set to true if *`this_facet_must_be_in_the_cz` is
among the internal or boundary facets of the conflict zone, and false otherwise.
\pre The starting cell (resp.\ facet) `c` must be in conflict with `p`.
@ -456,8 +456,8 @@ OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit,
OutputIteratorInternalFacets ifit,
bool *could_lock_zone = NULL,
const Facet *p_this_facet_must_be_in_the_cz = 0,
bool *p_the_facet_is_in_its_cz = 0);
const Facet *this_facet_must_be_in_the_cz = NULL,
bool *the_facet_is_in_its_cz = NULL);
/*!
This function is renamed `vertices_on_conflict_zone_boundary` since CGAL-3.8.

View File

@ -208,7 +208,7 @@ typedef TriangulationDataStructure_3::Facet_circulator Facet_circulator;
/*!
Concurrency tag (from the TDS).
*/
typedef TriangulationDataStructure_3::::Concurrency_tag Concurrency_tag;
typedef TriangulationDataStructure_3::Concurrency_tag Concurrency_tag;
/// @}
@ -605,8 +605,8 @@ The optional argument `start` is used as a starting place for the search.
The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the locate will
try to lock all the vertices along the walk. If it succeeds, *could_lock_zone
is true, otherwise it is false. In any case, the locked vertices are not
try to lock all the cells along the walk. If it succeeds, *could_lock_zone
is true, otherwise it is false. In any case, the locked cells are not
unlocked by `locate`, leaving this choice to the user.
*/
Cell_handle
@ -644,8 +644,8 @@ The optional argument `start` is used as a starting place for the search.
The optional argument `could_lock_zone` is used by the concurrency-safe
version of the triangulation. When the pointer is not null, the locate will
try to lock all the vertices along the walk. If it succeeds, *could_lock_zone
is true, otherwise it is false. In any case, the locked vertices are not
try to lock all the cells along the walk. If it succeeds, *could_lock_zone
is true, otherwise it is false. In any case, the locked cells are not
unlocked by `locate`, leaving this choice to the user.
*/
Cell_handle
@ -1190,7 +1190,7 @@ incident_cells(Vertex_handle v, OutputIterator cells) const;
Try to lock and copy the `Cell_handle`s of all cells incident to `v` into
`cells`.
Returns true in case of success. Otherwise, `cells` is emptied and the function
returns false. In any case, the locked vertices are not unlocked by
returns false. In any case, the locked cells are not unlocked by
`try_lock_and_get_incident_cells`, leaving this choice to the user.
\pre `t.dimension() == 3`, `v != Vertex_handle()`, `t.is_vertex(v)`.

View File

@ -224,6 +224,11 @@ triangulation class, described in Section \ref Triangulation3seclocpol.
Optionnally, the main Delaunay and regular triangulations algorithms (insert, remove)
support multi-core shared-memory architectures to take advantage of available parallelism.
For this purpose, the user must provide a model of the concept `SpatialLockDataStructure_3`,
such as the `Spatial_grid_lock_data_structure_3` class. This data structure
allows to lock point coordinates (x, y, z) in a 3D domain. When a thread owns the
lock on a point, no other thread can lock this point. Locking a facet (resp. a cell)
boils down to locking all its 3 (resp. 4) incident vertices.
\subsection Triangulation3secTraits The Geometric Traits Parameter

View File

@ -489,7 +489,8 @@ public:
find_conflicts(const Point &p, Cell_handle c,
OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit,
OutputIteratorInternalFacets ifit) const
OutputIteratorInternalFacets ifit,
bool *could_lock_zone = NULL) const
{
CGAL_triangulation_precondition(dimension() >= 2);
@ -504,7 +505,7 @@ public:
(c, tester,
make_triple(std::back_inserter(facets),
std::back_inserter(cells),
ifit)).third;
ifit, could_lock_zone)).third;
}
else {
Conflict_tester_3 tester(p, this);
@ -512,7 +513,7 @@ public:
(c, tester,
make_triple(std::back_inserter(facets),
std::back_inserter(cells),
ifit)).third;
ifit, could_lock_zone)).third;
}
// Reset the conflict flag on the boundary.
@ -535,12 +536,14 @@ public:
std::pair<OutputIteratorBoundaryFacets, OutputIteratorCells>
find_conflicts(const Point &p, Cell_handle c,
OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit) const
OutputIteratorCells cit,
bool *could_lock_zone = NULL) const
{
Triple<OutputIteratorBoundaryFacets,
OutputIteratorCells,
Emptyset_iterator> t = find_conflicts(p, c, bfit, cit,
Emptyset_iterator());
Emptyset_iterator(),
could_lock_zone);
return std::make_pair(t.first, t.second);
}

View File

@ -431,8 +431,8 @@ namespace CGAL {
OutputIteratorCells cit,
OutputIteratorInternalFacets ifit
, bool *could_lock_zone = NULL
, const Facet *p_this_facet_must_be_in_the_cz = 0
, bool *p_the_facet_is_in_its_cz = 0
, const Facet *this_facet_must_be_in_the_cz = NULL
, bool *the_facet_is_in_its_cz = NULL
) const
{
CGAL_triangulation_precondition(dimension() >= 2);
@ -451,8 +451,8 @@ namespace CGAL {
std::back_inserter(cells),
ifit)
, could_lock_zone
, p_this_facet_must_be_in_the_cz
, p_the_facet_is_in_its_cz
, this_facet_must_be_in_the_cz
, the_facet_is_in_its_cz
).third;
}
else {
@ -464,8 +464,8 @@ namespace CGAL {
std::back_inserter(cells),
ifit)
, could_lock_zone
, p_this_facet_must_be_in_the_cz
, p_the_facet_is_in_its_cz
, this_facet_must_be_in_the_cz
, the_facet_is_in_its_cz
).third;
}
@ -496,9 +496,8 @@ namespace CGAL {
Triple<OutputIteratorBoundaryFacets,
OutputIteratorCells,
Emptyset_iterator> t = find_conflicts(p, c, bfit, cit,
Emptyset_iterator()
, could_lock_zone
);
Emptyset_iterator(),
could_lock_zone);
return std::make_pair(t.first, t.second);
}

View File

@ -1045,7 +1045,7 @@ public:
Cell_handle c, int li, int lj,
const Conflict_tester &tester,
Hidden_points_visitor &hider,
bool *could_lock_zone = NULL);
bool *could_lock_zone = NULL);
template < class InputIterator >
std::ptrdiff_t insert(InputIterator first, InputIterator last)
@ -1145,29 +1145,28 @@ protected:
// - c is the current cell, which must be in conflict.
// - tester is the function object that tests if a cell is in conflict.
template <
class Conflict_test,
class OutputIteratorBoundaryFacets,
class OutputIteratorCells,
class OutputIteratorInternalFacets>
template <class Conflict_test,
class OutputIteratorBoundaryFacets,
class OutputIteratorCells,
class OutputIteratorInternalFacets>
Triple<OutputIteratorBoundaryFacets,
OutputIteratorCells,
OutputIteratorInternalFacets>
find_conflicts(
Cell_handle d,
const Conflict_test &tester,
Triple<OutputIteratorBoundaryFacets,
OutputIteratorCells,
OutputIteratorInternalFacets> it
Triple<OutputIteratorBoundaryFacets,
OutputIteratorCells,
OutputIteratorInternalFacets> it
, bool *could_lock_zone = NULL
, const Facet *p_this_facet_must_be_in_the_cz = 0
, bool *p_the_facet_is_in_its_cz = 0
, const Facet *this_facet_must_be_in_the_cz = NULL
, bool *the_facet_is_in_its_cz = NULL
) const
{
CGAL_triangulation_precondition( dimension()>=2 );
if (p_the_facet_is_in_its_cz)
*p_the_facet_is_in_its_cz = false;
if (the_facet_is_in_its_cz)
*the_facet_is_in_its_cz = false;
if (could_lock_zone)
*could_lock_zone = true;
@ -1217,10 +1216,10 @@ protected:
Facet f(c, i); // Internal facet.
// Is it the facet where're looking for?
if (p_this_facet_must_be_in_the_cz && p_the_facet_is_in_its_cz
&& f == *p_this_facet_must_be_in_the_cz)
if (this_facet_must_be_in_the_cz && the_facet_is_in_its_cz
&& f == *this_facet_must_be_in_the_cz)
{
*p_the_facet_is_in_its_cz = true;
*the_facet_is_in_its_cz = true;
}
if (c < test)
{
@ -1249,10 +1248,10 @@ protected:
Facet f(c, i); // Internal facet.
// Is it the facet where're looking for?
if (p_this_facet_must_be_in_the_cz && p_the_facet_is_in_its_cz
&& f == *p_this_facet_must_be_in_the_cz)
if (this_facet_must_be_in_the_cz && the_facet_is_in_its_cz
&& f == *this_facet_must_be_in_the_cz)
{
*p_the_facet_is_in_its_cz = true;
*the_facet_is_in_its_cz = true;
}
if (c < test)
@ -1271,13 +1270,13 @@ protected:
Facet f(c, i); // Boundary facet.
// Is it the facet where're looking for?
if (p_this_facet_must_be_in_the_cz
&& p_the_facet_is_in_its_cz
if (this_facet_must_be_in_the_cz
&& the_facet_is_in_its_cz
&&
(mirror_facet(f) == *p_this_facet_must_be_in_the_cz
|| f == *p_this_facet_must_be_in_the_cz) )
(mirror_facet(f) == *this_facet_must_be_in_the_cz
|| f == *this_facet_must_be_in_the_cz) )
{
*p_the_facet_is_in_its_cz = true;
*the_facet_is_in_its_cz = true;
}
*it.first++ = f;