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 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 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() 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. function, leaving this choice to the user.
*/ */
Vertex_handle insert(const Point & p, Vertex_handle insert(const Point & p,
@ -259,9 +259,9 @@ void remove(Vertex_handle v);
Removes the vertex `v` from the triangulation. Removes the vertex `v` from the triangulation.
This function is concurrency-safe if the triangulation is concurrency-safe. The removal will 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, 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 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 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 (resp. edges) `(t, i)` where the cell (resp. facet) `t` is in
conflict, but `t->neighbor(i)` is not. 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 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 to decide the insertion of a point after seeing which elements of the
triangulation are affected. triangulation are affected.
@ -415,7 +421,7 @@ class OutputIteratorCells>
std::pair<OutputIteratorBoundaryFacets, OutputIteratorCells> std::pair<OutputIteratorBoundaryFacets, OutputIteratorCells>
find_conflicts(Point p, Cell_handle c, find_conflicts(Point p, Cell_handle c,
OutputIteratorBoundaryFacets bfit, OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit); OutputIteratorCells cit, bool *could_lock_zone = NULL);
/*! /*!
Same as the other `find_conflicts()` function, except that it also 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 - `ifit`: the facets (resp. edges) inside the hole, that is, delimiting
two cells (resp facets) in conflict. 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. Returns the `Triple` composed of the resulting output iterators.
\pre `dt`.`dimension()` \f$ \geq2\f$, and `c` is in conflict with `p`. \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, find_conflicts(Point p, Cell_handle c,
OutputIteratorBoundaryFacets bfit, OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit, OutputIteratorCells cit,
OutputIteratorInternalFacets ifit); OutputIteratorInternalFacets ifit,
bool *could_lock_zone = NULL);
/*! /*!
This function is renamed `vertices_on_conflict_zone_boundary` since CGAL-3.8. 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 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 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, 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, Vertex_handle insert(const Weighted_point & p,
Cell_handle start = Cell_handle(), bool *could_lock_zone = NULL); 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. Removes the vertex `v` from the triangulation.
This function is concurrency-safe if the triangulation is concurrency-safe. The removal will 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, 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 This function will try to remove `v` only if the removal does not
decrease the dimension. decrease the dimension.
@ -425,17 +425,17 @@ Compute the conflicts with `p`.
@param cit The cells (resp. facets) in conflict 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 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 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 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, 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. the locked cells are not unlocked by the function, leaving this choice to the user.
@param p_this_facet_must_be_in_the_cz @param 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 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). if this facet is in the conflict zone (it may be internal as well as boundary).
@param p_the_facet_is_in_its_cz @param 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. 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 *`p_this_facet_must_be_in_the_cz` is 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. 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`. \pre The starting cell (resp.\ facet) `c` must be in conflict with `p`.
@ -456,8 +456,8 @@ OutputIteratorBoundaryFacets bfit,
OutputIteratorCells cit, OutputIteratorCells cit,
OutputIteratorInternalFacets ifit, OutputIteratorInternalFacets ifit,
bool *could_lock_zone = NULL, bool *could_lock_zone = NULL,
const Facet *p_this_facet_must_be_in_the_cz = 0, const Facet *this_facet_must_be_in_the_cz = NULL,
bool *p_the_facet_is_in_its_cz = 0); bool *the_facet_is_in_its_cz = NULL);
/*! /*!
This function is renamed `vertices_on_conflict_zone_boundary` since CGAL-3.8. 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). 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 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 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 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 vertices are not is true, otherwise it is false. In any case, the locked cells are not
unlocked by `locate`, leaving this choice to the user. unlocked by `locate`, leaving this choice to the user.
*/ */
Cell_handle 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 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 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 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 vertices are not is true, otherwise it is false. In any case, the locked cells are not
unlocked by `locate`, leaving this choice to the user. unlocked by `locate`, leaving this choice to the user.
*/ */
Cell_handle 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 Try to lock and copy the `Cell_handle`s of all cells incident to `v` into
`cells`. `cells`.
Returns true in case of success. Otherwise, `cells` is emptied and the function 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. `try_lock_and_get_incident_cells`, leaving this choice to the user.
\pre `t.dimension() == 3`, `v != Vertex_handle()`, `t.is_vertex(v)`. \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) Optionnally, the main Delaunay and regular triangulations algorithms (insert, remove)
support multi-core shared-memory architectures to take advantage of available parallelism. 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 \subsection Triangulation3secTraits The Geometric Traits Parameter

View File

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

View File

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

View File

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