mirror of https://github.com/CGAL/cgal
Corrected a rare race condition.
The few bad facets that are created during the "cell refinement" step are treated immediately inside the thread which created them.
This commit is contained in:
parent
4fdf647428
commit
a520f3cbf0
|
|
@ -26,6 +26,8 @@
|
|||
#endif
|
||||
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
#include <algorithm>
|
||||
|
||||
#include <tbb/tbb.h>
|
||||
|
||||
#include <CGAL/hilbert_sort.h>
|
||||
|
|
@ -38,6 +40,9 @@
|
|||
#include <CGAL/Profile_counter.h>
|
||||
#endif
|
||||
|
||||
// CJTODO TEMP TEST
|
||||
extern bool g_is_set_cell_active;
|
||||
|
||||
// CJTODO TEMP: not thread-safe => move it to Mesher_3
|
||||
extern CGAL::Bbox_3 g_bbox;
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
|
|
@ -52,9 +57,13 @@ namespace CGAL {
|
|||
enum Mesher_level_conflict_status {
|
||||
NO_CONFLICT = 0,
|
||||
CONFLICT_BUT_ELEMENT_CAN_BE_RECONSIDERED,
|
||||
CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED
|
||||
CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
, ELEMENT_WAS_A_ZOMBIE
|
||||
#endif
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
, COULD_NOT_LOCK_ZONE
|
||||
, COULD_NOT_LOCK_ELEMENT
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
@ -94,6 +103,15 @@ struct Null_mesher_level {
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
void add_to_TLS_lists(bool) {}
|
||||
void splice_local_lists() {}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void before_next_element_refinement_in_superior(Mesh_visitor visitor) {}
|
||||
void before_next_element_refinement() {}
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
std::string debug_info_class_name_impl() const
|
||||
{
|
||||
return "Null_mesher_level";
|
||||
|
|
@ -237,7 +255,7 @@ public:
|
|||
}
|
||||
|
||||
/** Retrieves the next element that could be refined. */
|
||||
Element get_next_element()
|
||||
Element get_next_element() const
|
||||
{
|
||||
return derived().get_next_element_impl();
|
||||
}
|
||||
|
|
@ -253,6 +271,71 @@ public:
|
|||
{
|
||||
return derived().circumcenter_impl(e);
|
||||
}
|
||||
|
||||
void add_to_TLS_lists(bool add)
|
||||
{
|
||||
derived().add_to_TLS_lists_impl(add);
|
||||
}
|
||||
void splice_local_lists()
|
||||
{
|
||||
derived().splice_local_lists_impl();
|
||||
}
|
||||
|
||||
bool no_longer_local_element_to_refine()
|
||||
{
|
||||
return derived().no_longer_local_element_to_refine_impl();
|
||||
}
|
||||
|
||||
Element get_next_local_element()
|
||||
{
|
||||
return derived().get_next_local_element_impl();
|
||||
}
|
||||
|
||||
void pop_next_local_element()
|
||||
{
|
||||
derived().pop_next_local_element_impl();
|
||||
}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void treat_local_refinement_queue(Mesh_visitor visitor)
|
||||
{
|
||||
// We treat the elements of the local (TLS) refinement queue
|
||||
while (no_longer_local_element_to_refine() == false)
|
||||
{
|
||||
typedef typename Derived::Container::Element Container_element;
|
||||
Container_element ce = derived().get_next_local_raw_element_impl().second;
|
||||
|
||||
const Mesher_level_conflict_status status =
|
||||
try_lock_and_refine_element(ce, visitor);
|
||||
|
||||
switch (status)
|
||||
{
|
||||
case NO_CONFLICT:
|
||||
case CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED:
|
||||
case ELEMENT_WAS_A_ZOMBIE:
|
||||
pop_next_local_element();
|
||||
break;
|
||||
|
||||
case COULD_NOT_LOCK_ZONE:
|
||||
//tbb::this_tbb_thread::yield();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void before_next_element_refinement_in_superior(Mesh_visitor visitor)
|
||||
{
|
||||
derived().before_next_element_refinement_in_superior_impl(visitor);
|
||||
}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void before_next_element_refinement(Mesh_visitor visitor)
|
||||
{
|
||||
derived().before_next_element_refinement_impl();
|
||||
previous_level.before_next_element_refinement_in_superior(
|
||||
visitor.previous_level());
|
||||
}
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
/** Gives the point that should be inserted to refine the element \c e */
|
||||
|
|
@ -377,7 +460,11 @@ public:
|
|||
{
|
||||
previous_level.refine(visitor.previous_level());
|
||||
if(! no_longer_element_to_refine() )
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
process_a_batch_of_elements(visitor);
|
||||
#else
|
||||
process_one_element(visitor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -422,100 +509,6 @@ public:
|
|||
return e.first;
|
||||
}
|
||||
|
||||
bool try_lock_cells_from_element(const Cell_handle &e) const
|
||||
{
|
||||
return e->try_lock();
|
||||
}
|
||||
bool try_lock_cells_from_element(const Facet &e) const
|
||||
{
|
||||
return e.first->try_lock();
|
||||
/*if (e.first->try_lock())
|
||||
{
|
||||
Facet mf = derived().triangulation_ref_impl().mirror_facet(e);
|
||||
if (!mf.first->try_lock())
|
||||
{
|
||||
e.first->unlock();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}*/
|
||||
}
|
||||
|
||||
template< typename Elt >
|
||||
bool try_lock_element(const Elt &element, int lock_radius = 0)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
// Lock the element area on the grid
|
||||
Vertex_handle vertices[4];
|
||||
get_valid_vertices_of_element(element, vertices);
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
const Vertex_handle null_vertex;
|
||||
Vertex_handle vh = vertices[iVertex];
|
||||
if (vh != null_vertex)
|
||||
{
|
||||
success = g_lock_grid.try_lock(vh->point(), lock_radius).first;
|
||||
}
|
||||
}
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
success = try_lock_cells_from_element(element);
|
||||
# endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
// Spin while not successful
|
||||
template< typename Elt >
|
||||
void lock_element(const Elt &element)
|
||||
{
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
// Lock the element area on the grid
|
||||
Vertex_handle vertices[4];
|
||||
get_valid_vertices_of_element(element, vertices);
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
const Vertex_handle null_vertex;
|
||||
Vertex_handle vh = vertices[iVertex];
|
||||
if (vh != null_vertex)
|
||||
{
|
||||
std::pair<bool, int> r = g_lock_grid.try_lock(vh->point());
|
||||
bool success = r.first;
|
||||
while( !success )
|
||||
{
|
||||
// Active wait
|
||||
tbb::this_tbb_thread::yield();
|
||||
success = g_lock_grid.try_lock(r.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
/*Cell_handle ch = get_cell_from_element(element);
|
||||
bool success = ch->try_lock();
|
||||
while( !success )
|
||||
{
|
||||
// Active wait
|
||||
tbb::this_tbb_thread::yield();
|
||||
success = ch->try_lock();
|
||||
}*/
|
||||
bool success = try_lock_cells_from_element(ch);
|
||||
while( !success )
|
||||
{
|
||||
// Active wait
|
||||
tbb::this_tbb_thread::yield();
|
||||
success = try_lock_cells_from_element(ch);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
void unlock_all_thread_local_elements()
|
||||
{
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
|
|
@ -541,7 +534,6 @@ public:
|
|||
template <class Mesh_visitor>
|
||||
void process_a_batch_of_elements(Mesh_visitor visitor)
|
||||
{
|
||||
|
||||
typedef typename Derived::Container::Element Container_element;
|
||||
typedef typename Derived::Container::Quality Container_quality;
|
||||
|
||||
|
|
@ -553,12 +545,7 @@ public:
|
|||
circumcenters.reserve(ELEMENT_BATCH_SIZE);
|
||||
std::vector<std::ptrdiff_t> indices;
|
||||
indices.reserve(ELEMENT_BATCH_SIZE);
|
||||
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
static Profile_branch_counter_3 bcounter(
|
||||
std::string("early withdrawals / late withdrawals / successes [") + debug_info_class_name() + "]");
|
||||
# endif
|
||||
|
||||
|
||||
/*int batch_size = ELEMENT_BATCH_SIZE;
|
||||
if (debug_info_class_name() == "Refine_facets_3")
|
||||
batch_size = 1;*/
|
||||
|
|
@ -588,7 +575,7 @@ public:
|
|||
// Search_traits(&(circumcenters[0])) );
|
||||
//hilbert_sort( indices.begin(), indices.end(), Hilbert_sort_median_policy(),
|
||||
// Search_traits(&(circumcenters[0])) );
|
||||
|
||||
std::random_shuffle(indices.begin(), indices.end());
|
||||
|
||||
/*for( size_t i = 0 ; i < iElt ; ++i)
|
||||
{
|
||||
|
|
@ -599,7 +586,7 @@ public:
|
|||
{
|
||||
const Mesher_level_conflict_status result
|
||||
= try_to_refine_element(derived().extract_element_from_container_value(e),
|
||||
visitor);
|
||||
visitor);
|
||||
if (result == CONFLICT_BUT_ELEMENT_CAN_BE_RECONSIDERED)
|
||||
derived().insert_raw_element(raw_elements[i]);
|
||||
}
|
||||
|
|
@ -612,111 +599,62 @@ public:
|
|||
// CJTODO: TEST
|
||||
if (iElt > 20)
|
||||
{
|
||||
derived().addToTLSLists(true);
|
||||
//g_is_set_cell_active = false;
|
||||
previous_level.add_to_TLS_lists(true);
|
||||
add_to_TLS_lists(true);
|
||||
tbb::parallel_for(
|
||||
tbb::blocked_range<size_t>( 0, iElt, 30 ),
|
||||
tbb::blocked_range<size_t>( 0, iElt, MESH_3_REFINEMENT_GRAINSIZE ),
|
||||
[&] (const tbb::blocked_range<size_t>& r)
|
||||
{
|
||||
for( size_t i = r.begin() ; i != r.end() ; )
|
||||
{
|
||||
int index = indices[i];
|
||||
before_next_element_refinement(visitor);
|
||||
|
||||
Derived &derivd = derived();
|
||||
//Container_element ce = raw_elements[index].second;
|
||||
std::ptrdiff_t index = indices[i];
|
||||
Container_element ce = container_elements[index];
|
||||
if( !derivd.is_zombie(ce) )
|
||||
{
|
||||
//static tbb::queuing_mutex mutex;
|
||||
//tbb::queuing_mutex::scoped_lock lock(mutex);
|
||||
|
||||
const Mesher_level_conflict_status status =
|
||||
try_lock_and_refine_element(ce, visitor);
|
||||
|
||||
// Lock the element area on the grid
|
||||
Element element = derivd.extract_element_from_container_value(ce);
|
||||
bool locked = try_lock_element(element, FIRST_GRID_LOCK_RADIUS);
|
||||
|
||||
if( locked )
|
||||
{
|
||||
// Test it again as it may have changed in the meantime
|
||||
if( !derivd.is_zombie(ce) )
|
||||
{
|
||||
//Global_mutex_type::scoped_lock lock;
|
||||
//if( lock.try_acquire(g_global_mutex) )
|
||||
//{
|
||||
const Mesher_level_conflict_status result
|
||||
= try_to_refine_element(element, visitor);
|
||||
|
||||
//lock.release();
|
||||
|
||||
if (result == CONFLICT_BUT_ELEMENT_CAN_BE_RECONSIDERED)
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
++bcounter; // It's not an withdrawal
|
||||
# endif
|
||||
// We try it again right now!
|
||||
//CJTODO : faire une boucle pour reessayer tout de suite?
|
||||
}
|
||||
else if (result == COULD_NOT_LOCK_ZONE)
|
||||
{
|
||||
// Swap indices[i] and indices[i+1]
|
||||
if (i+1 != r.end())
|
||||
{
|
||||
ptrdiff_t tmp = indices[i+1];
|
||||
indices[i+1] = indices[i];
|
||||
indices[i] = tmp;
|
||||
}
|
||||
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
bcounter.increment_branch_1(); // THIS is a late withdrawal!
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
++bcounter;
|
||||
# endif
|
||||
++i;
|
||||
|
||||
}
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
++i;
|
||||
}
|
||||
|
||||
// Unlock
|
||||
unlock_all_thread_local_elements();
|
||||
}
|
||||
// else, we try it again
|
||||
else
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
bcounter.increment_branch_2(); // THIS is an early withdrawal!
|
||||
# endif
|
||||
// Unlock
|
||||
unlock_all_thread_local_elements();
|
||||
tbb::this_tbb_thread::yield();
|
||||
}
|
||||
}
|
||||
else
|
||||
switch (status)
|
||||
{
|
||||
++i;
|
||||
case NO_CONFLICT:
|
||||
case CONFLICT_AND_ELEMENT_SHOULD_BE_DROPPED:
|
||||
case ELEMENT_WAS_A_ZOMBIE:
|
||||
++i;
|
||||
break;
|
||||
|
||||
case COULD_NOT_LOCK_ZONE:
|
||||
// Swap indices[i] and indices[i+1]
|
||||
/*if (i+1 != r.end())
|
||||
{
|
||||
ptrdiff_t tmp = indices[i+1];
|
||||
indices[i+1] = indices[i];
|
||||
indices[i] = tmp;
|
||||
}*/
|
||||
|
||||
// CJTODO: TEST THAT
|
||||
// Swap indices[i] and indices[last]
|
||||
ptrdiff_t tmp = indices[r.end() - 1];
|
||||
indices[r.end() - 1] = indices[i];
|
||||
indices[i] = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
derived().spliceLocalLists();
|
||||
derived().addToTLSLists(false);
|
||||
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_VERBOSE
|
||||
std::cerr << " batch done." << std::endl;
|
||||
# endif
|
||||
splice_local_lists();
|
||||
//previous_level.splice_local_lists(); // useless
|
||||
previous_level.add_to_TLS_lists(false);
|
||||
add_to_TLS_lists(false);
|
||||
//g_is_set_cell_active = true;
|
||||
}
|
||||
// Go sequential
|
||||
else
|
||||
{
|
||||
for (int i = 0 ; i < iElt ; )
|
||||
{
|
||||
int index = indices[i];
|
||||
std::ptrdiff_t index = indices[i];
|
||||
|
||||
Derived &derivd = derived();
|
||||
//Container_element ce = raw_elements[index].second;
|
||||
|
|
@ -742,6 +680,10 @@ public:
|
|||
unlock_all_thread_local_elements();
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_VERBOSE
|
||||
std::cerr << " batch done." << std::endl;
|
||||
# endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -852,6 +794,86 @@ public:
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
template <typename Container_element, typename Mesh_visitor>
|
||||
Mesher_level_conflict_status
|
||||
try_lock_and_refine_element(const Container_element &ce, Mesh_visitor visitor)
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
static Profile_branch_counter_3 bcounter(
|
||||
std::string("early withdrawals / late withdrawals / successes [") + debug_info_class_name() + "]");
|
||||
# endif
|
||||
|
||||
Mesher_level_conflict_status result;
|
||||
Derived &derivd = derived();
|
||||
if( !derivd.is_zombie(ce) )
|
||||
{
|
||||
// Lock the element area on the grid
|
||||
Element element = derivd.extract_element_from_container_value(ce);
|
||||
bool locked = triangulation().try_lock_element(
|
||||
element, MESH_3_FIRST_GRID_LOCK_RADIUS);
|
||||
|
||||
if( locked )
|
||||
{
|
||||
// Test it again as it may have changed in the meantime
|
||||
if( !derivd.is_zombie(ce) )
|
||||
{
|
||||
result = try_to_refine_element(element, visitor);
|
||||
|
||||
//lock.release();
|
||||
|
||||
if (result == CONFLICT_BUT_ELEMENT_CAN_BE_RECONSIDERED)
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
++bcounter; // It's not a withdrawal
|
||||
# endif
|
||||
// We try it again right now!
|
||||
}
|
||||
else if (result == COULD_NOT_LOCK_ZONE)
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
bcounter.increment_branch_1(); // THIS is a late withdrawal!
|
||||
# endif
|
||||
}
|
||||
else
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
++bcounter;
|
||||
# endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ELEMENT_WAS_A_ZOMBIE;
|
||||
}
|
||||
|
||||
// Unlock
|
||||
unlock_all_thread_local_elements();
|
||||
}
|
||||
// else, we try it again
|
||||
else
|
||||
{
|
||||
# ifdef CGAL_CONCURRENT_MESH_3_PROFILING
|
||||
bcounter.increment_branch_2(); // THIS is an early withdrawal!
|
||||
# endif
|
||||
// Unlock
|
||||
unlock_all_thread_local_elements();
|
||||
|
||||
tbb::this_tbb_thread::yield();
|
||||
result = COULD_NOT_LOCK_ELEMENT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = ELEMENT_WAS_A_ZOMBIE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
template <class Mesh_visitor>
|
||||
|
|
@ -888,7 +910,7 @@ public:
|
|||
while(! is_algorithm_done() )
|
||||
{
|
||||
if( previous_level.try_to_insert_one_point(visitor.previous_level()) )
|
||||
return true;
|
||||
return true;
|
||||
if(! no_longer_element_to_refine() )
|
||||
if( process_one_element(visitor) )
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <CGAL/Mesh_triangulation_3.h>
|
||||
#include <CGAL/Mesh_complex_3_in_triangulation_3.h>
|
||||
#include <CGAL/Triangulation_lazy_ds_cell_base_3.h>
|
||||
|
||||
#include <CGAL/Mesh_3/Robust_intersection_traits_3.h>
|
||||
#include <CGAL/Polyhedral_mesh_domain_3.h>
|
||||
|
|
@ -71,23 +70,7 @@ typedef Wrapper<Kernel> Function
|
|||
typedef CGAL::Mesh_3::Labeled_mesh_domain_3<Function_wrapper, Kernel> Function_mesh_domain;
|
||||
|
||||
// Triangulation
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
typedef CGAL::Kernel_traits<Polyhedral_mesh_domain>::Kernel PMDKernel;
|
||||
typedef CGAL::details::Mesh_geom_traits_generator<PMDKernel>::type Geom_traits;
|
||||
typedef CGAL::Triangulation_lazy_ds_cell_base_3<> DS_cell_base;
|
||||
typedef CGAL::Triangulation_cell_base_with_circumcenter_3<
|
||||
Geom_traits, DS_cell_base> Cell_base_with_cc;
|
||||
typedef CGAL::Regular_triangulation_cell_base_3<
|
||||
Geom_traits, Cell_base_with_cc> Regular_cell_base;
|
||||
typedef CGAL::Mesh_triangulation_3<
|
||||
Polyhedral_mesh_domain,
|
||||
Kernel,
|
||||
Geom_traits,
|
||||
Regular_cell_base>::type Tr;
|
||||
#else
|
||||
typedef CGAL::Mesh_triangulation_3<Polyhedral_mesh_domain>::type Tr;
|
||||
#endif
|
||||
|
||||
typedef CGAL::Mesh_triangulation_3<Polyhedral_mesh_domain>::type Tr;
|
||||
|
||||
// 3D complex
|
||||
typedef CGAL::Mesh_complex_3_in_triangulation_3<Tr> C3t3;
|
||||
|
|
|
|||
|
|
@ -34,13 +34,16 @@
|
|||
#include <CGAL/Mesh_3/Locking_data_structures.h> // CJODO TEMP?
|
||||
#include <CGAL/BBox_3.h>
|
||||
|
||||
// CJTODO TEMP TEST
|
||||
bool g_is_set_cell_active = true;
|
||||
|
||||
Global_mutex_type g_global_mutex; // CJTODO: temporary
|
||||
|
||||
// CJTODO TEMP: not thread-safe => move it to Mesher_3
|
||||
// Elephant.off => BBox (x,y,z): [ -0.358688, 0.356308 ], [ -0.498433, 0.49535 ], [ -0.298931, 0.298456 ]
|
||||
CGAL::Bbox_3 g_bbox(-0.35, 0.35, -0.5, 0.5, -0.3, 0.3);
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
CGAL::Mesh_3::Refinement_grid_type g_lock_grid(g_bbox, LOCKING_GRID_NUM_CELLS_PER_AXIS);
|
||||
CGAL::Mesh_3::Refinement_grid_type g_lock_grid(g_bbox, MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS);
|
||||
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
# include <utility>
|
||||
|
|
@ -62,13 +65,14 @@ Meshing_thread* cgal_code_mesh_3(const Polyhedron*,
|
|||
const double tets_sizing,
|
||||
const double tet_shape);
|
||||
|
||||
// CJTODO TEMP
|
||||
/*Meshing_thread* cgal_code_mesh_3(const Image*,
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
Meshing_thread* cgal_code_mesh_3(const Image*,
|
||||
const double angle,
|
||||
const double sizing,
|
||||
const double approx,
|
||||
const double tets_sizing,
|
||||
const double tet_shape);*/
|
||||
const double tet_shape);
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_IMPLICIT_FUNCTIONS
|
||||
Meshing_thread* cgal_code_mesh_3(const Implicit_function_interface*,
|
||||
|
|
@ -261,9 +265,9 @@ void Mesh_3_plugin::mesh_3()
|
|||
angle, facet_sizing, approx,
|
||||
tet_sizing, radius_edge);
|
||||
}
|
||||
// Image
|
||||
// CJTODO TEMP
|
||||
/*else if( NULL != image_item )
|
||||
// Image
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
else if( NULL != image_item )
|
||||
{
|
||||
const Image* pImage = image_item->image();
|
||||
if( NULL == pImage )
|
||||
|
|
@ -275,7 +279,9 @@ void Mesh_3_plugin::mesh_3()
|
|||
thread = cgal_code_mesh_3(pImage,
|
||||
angle, facet_sizing, approx,
|
||||
tet_sizing, radius_edge);
|
||||
}*/
|
||||
}
|
||||
#endif
|
||||
|
||||
// Function
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_IMPLICIT_FUNCTIONS
|
||||
else if( NULL != function_item )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// CJTODO TEMP
|
||||
/*#include "config.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
|
||||
#include "C3t3_type.h"
|
||||
#include "Scene_c3t3_item.h"
|
||||
|
|
@ -35,4 +36,5 @@ Meshing_thread* cgal_code_mesh_3(const Image* pImage,
|
|||
Mesh_function* p_mesh_function = new Mesh_function(p_new_item->c3t3(), p_domain, param);
|
||||
return new Meshing_thread(p_mesh_function, p_new_item);
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
|
@ -190,7 +190,9 @@ launch()
|
|||
// Ensure c3t3 is ok (usefull if process has been stop by the user)
|
||||
mesher_->fix_c3t3();
|
||||
|
||||
#ifdef WIN32
|
||||
QSound::play("Ding.wav"); // CJTODO TEMP
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,16 @@
|
|||
#include <CGAL/Mesh_3/Locking_data_structures.h> // CJODO TEMP?
|
||||
#include <CGAL/BBox_3.h>
|
||||
|
||||
// CJTODO TEMP TEST
|
||||
bool g_is_set_cell_active = true;
|
||||
|
||||
//Global_mutex_type g_global_mutex; // CJTODO: temporary
|
||||
|
||||
// CJTODO TEMP: not thread-safe => move it to Mesher_3
|
||||
// Elephant.off => BBox (x,y,z): [ -0.358688, 0.356308 ], [ -0.498433, 0.49535 ], [ -0.298931, 0.298456 ]
|
||||
CGAL::Bbox_3 g_bbox(-0.35, 0.35, -0.5, 0.5, -0.3, 0.3);
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
CGAL::Mesh_3::Refinement_grid_type g_lock_grid(g_bbox, LOCKING_GRID_NUM_CELLS_PER_AXIS);
|
||||
CGAL::Mesh_3::Refinement_grid_type g_lock_grid(g_bbox, MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS);
|
||||
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
# include <utility>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#ifdef CONCURRENT_MESH_3
|
||||
// In case some code uses CGAL_PROFILE, it needs to be concurrent
|
||||
#define CGAL_CONCURRENT_PROFILE
|
||||
#define CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
#endif
|
||||
|
||||
#include <cmath>
|
||||
|
|
@ -287,7 +288,7 @@
|
|||
//#include <CGAL/Mesh_3/Triangle_accessor_primitive.h>
|
||||
//#include <CGAL/Mesh_3/Triangulation_lazy_ds_cell_base_3.h>
|
||||
//#include <CGAL/Mesh_3/utilities.h>
|
||||
#include <CGAL/Mesh_cell_base_3.h>
|
||||
//#include <CGAL/Mesh_cell_base_3.h>
|
||||
#include <CGAL/Mesh_cell_criteria_3.h>
|
||||
#include <CGAL/Mesh_constant_domain_field_3.h>
|
||||
#include <CGAL/Mesh_criteria_3.h>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@
|
|||
# define CGAL_POLYHEDRON_DEMO_USE_SURFACE_MESHER
|
||||
#endif
|
||||
|
||||
#define CGAL_MESH_3_DEMO_ACTIVATE_IMPLICIT_FUNCTIONS
|
||||
//#define CGAL_MESH_3_DEMO_ACTIVATE_IMPLICIT_FUNCTIONS
|
||||
//#define CGAL_MESH_3_DEMO_ACTIVATE_SEGMENTED_IMAGES
|
||||
|
||||
// ==========================================================================
|
||||
// CONCURRENCY
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
# define CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
// In case some code uses CGAL_PROFILE, it needs to be concurrent
|
||||
# define CGAL_CONCURRENT_PROFILE
|
||||
//# define CGAL_CONCURRENT_MESH_3_VERBOSE
|
||||
# define CGAL_CONCURRENT_MESH_3_VERBOSE
|
||||
|
||||
// ==========================================================================
|
||||
// Locking strategy
|
||||
|
|
@ -46,10 +47,11 @@
|
|||
# ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
//# define CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK
|
||||
# define CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
# define CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS
|
||||
//# define CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS
|
||||
|
||||
const int LOCKING_GRID_NUM_CELLS_PER_AXIS = 25;
|
||||
const int FIRST_GRID_LOCK_RADIUS = 2;
|
||||
const int MESH_3_LOCKING_GRID_NUM_CELLS_PER_AXIS = 30;
|
||||
const int MESH_3_FIRST_GRID_LOCK_RADIUS = 2;
|
||||
const int MESH_3_REFINEMENT_GRAINSIZE = 10;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK
|
||||
# include <tbb/recursive_mutex.h>
|
||||
|
|
@ -58,7 +60,7 @@
|
|||
# endif
|
||||
|
||||
// ==========================================================================
|
||||
// CJTODO: temp
|
||||
// CJTODO TEMP
|
||||
// ==========================================================================
|
||||
# include <tbb/tbb.h>
|
||||
typedef tbb::recursive_mutex Global_mutex_type;
|
||||
|
|
@ -68,7 +70,7 @@
|
|||
// Concurrency Parameters
|
||||
// ==========================================================================
|
||||
|
||||
const size_t ELEMENT_BATCH_SIZE = 3000;
|
||||
const size_t ELEMENT_BATCH_SIZE = 30000;
|
||||
|
||||
// ==========================================================================
|
||||
// Profiling
|
||||
|
|
|
|||
|
|
@ -1527,11 +1527,18 @@ get_conflict_zone_topo_change(const Vertex_handle& vertex,
|
|||
return conflict_cells;
|
||||
|
||||
// Find conflict zone
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
bool could_lock_zone = true;
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
tr_.find_conflicts(conflict_point,
|
||||
cell,
|
||||
CGAL::Emptyset_iterator(),
|
||||
std::back_inserter(deleted_cells),
|
||||
CGAL::Emptyset_iterator());
|
||||
CGAL::Emptyset_iterator()
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
, could_lock_zone
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
);
|
||||
|
||||
// Compute union of conflict_point conflict zone and triangulation_vertex
|
||||
// incident cells
|
||||
|
|
|
|||
|
|
@ -84,9 +84,6 @@ public:
|
|||
|
||||
bool try_lock(int cell_index)
|
||||
{
|
||||
//if (cell_index == 0) // CJTODO TEMP
|
||||
// return true;
|
||||
|
||||
bool ret = false;
|
||||
// Already locked by this thread?
|
||||
if (m_tls_grids.local()[cell_index])
|
||||
|
|
@ -297,9 +294,6 @@ public:
|
|||
|
||||
bool try_lock(int cell_index)
|
||||
{
|
||||
//if (cell_index == 0) // CJTODO TEMP
|
||||
// return true;
|
||||
|
||||
bool ret = false;
|
||||
// Already locked by this thread?
|
||||
if (m_tls_grids.local()[cell_index])
|
||||
|
|
@ -460,8 +454,8 @@ protected:
|
|||
TLS_locked_cells m_tls_locked_cells;
|
||||
};
|
||||
|
||||
//typedef Simple_grid_locking_ds_with_mutex Refinement_grid_type;
|
||||
typedef Simple_grid_locking_ds Refinement_grid_type;
|
||||
typedef Simple_grid_locking_ds_with_mutex Refinement_grid_type;
|
||||
//typedef Simple_grid_locking_ds Refinement_grid_type;
|
||||
|
||||
|
||||
} //namespace Mesh_3
|
||||
|
|
|
|||
|
|
@ -181,6 +181,20 @@ public:
|
|||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
template <class Mesh_visitor>
|
||||
void process_a_batch_of_elements_impl(Mesh_visitor visitor);
|
||||
|
||||
Point circumcenter_impl(const Cell_handle& cell) const
|
||||
{
|
||||
return r_tr_.dual(cell);
|
||||
}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void before_next_element_refinement_in_superior_impl(Mesh_visitor)
|
||||
{
|
||||
}
|
||||
|
||||
void before_next_element_refinement_impl()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
|
|
@ -194,11 +208,6 @@ public:
|
|||
{
|
||||
return extract_element_from_container_value(Container_::get_next_element_impl());
|
||||
}
|
||||
|
||||
Point circumcenter_impl(const Cell_handle& cell) const
|
||||
{
|
||||
return r_tr_.dual(cell);
|
||||
};
|
||||
#endif
|
||||
|
||||
// Gets the point to insert from the element to refine
|
||||
|
|
@ -385,7 +394,7 @@ scan_triangulation_impl()
|
|||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_SCAN_TRIANGULATION
|
||||
|
||||
addToTLSLists(true);
|
||||
add_to_TLS_lists(true);
|
||||
/*
|
||||
// WITH PARALLEL_FOR
|
||||
WallClockTimer t2;
|
||||
|
|
@ -414,9 +423,9 @@ scan_triangulation_impl()
|
|||
treat_new_cell( c );
|
||||
});
|
||||
|
||||
spliceLocalLists();
|
||||
splice_local_lists();
|
||||
//std::cerr << "Parallel_for - splice done: " << t2.elapsed() << " seconds." << std::endl;
|
||||
addToTLSLists(false);
|
||||
add_to_TLS_lists(false);
|
||||
#else
|
||||
for(Finite_cell_iterator cell_it = r_tr_.finite_cells_begin();
|
||||
cell_it != r_tr_.finite_cells_end();
|
||||
|
|
|
|||
|
|
@ -187,6 +187,24 @@ public:
|
|||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
template <class Mesh_visitor>
|
||||
void process_a_batch_of_elements_impl(Mesh_visitor visitor);
|
||||
|
||||
Point circumcenter_impl(const Facet& facet) const
|
||||
{
|
||||
return get_facet_surface_center(facet);
|
||||
}
|
||||
|
||||
template <typename Mesh_visitor>
|
||||
void before_next_element_refinement_in_superior_impl(Mesh_visitor visitor)
|
||||
{
|
||||
// Before refining any cell, we refine the facets in the local refinement
|
||||
// queue
|
||||
this->treat_local_refinement_queue(visitor);
|
||||
}
|
||||
|
||||
void before_next_element_refinement_impl()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
|
|
@ -198,14 +216,20 @@ public:
|
|||
|
||||
Facet get_next_element_impl() const
|
||||
{
|
||||
return extract_element_from_container_value(Container_::get_next_element_impl());
|
||||
return extract_element_from_container_value(
|
||||
Container_::get_next_element_impl());
|
||||
}
|
||||
|
||||
Point circumcenter_impl(const Facet& facet) const
|
||||
|
||||
# ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
Facet get_next_local_element_impl()
|
||||
{
|
||||
return get_facet_surface_center(facet);
|
||||
};
|
||||
return extract_element_from_container_value(
|
||||
Container_::get_next_local_element_impl());
|
||||
}
|
||||
# endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/// Gets the point to insert from the element to refine
|
||||
Point refinement_point_impl(const Facet& facet) const
|
||||
|
|
@ -547,7 +571,7 @@ scan_triangulation_impl()
|
|||
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_SCAN_TRIANGULATION
|
||||
addToTLSLists(true);
|
||||
add_to_TLS_lists(true);
|
||||
// PARALLEL_DO
|
||||
tbb::parallel_do(r_tr_.finite_facets_begin(), r_tr_.finite_facets_end(),
|
||||
[=]( const Facet &facet ) { // CJTODO: lambdas ok?
|
||||
|
|
@ -555,8 +579,8 @@ scan_triangulation_impl()
|
|||
Facet f = facet;
|
||||
treat_new_facet( f );
|
||||
});
|
||||
spliceLocalLists();
|
||||
addToTLSLists(false);
|
||||
splice_local_lists();
|
||||
add_to_TLS_lists(false);
|
||||
|
||||
#else
|
||||
for(Finite_facet_iterator facet_it = r_tr_.finite_facets_begin();
|
||||
|
|
@ -602,23 +626,7 @@ test_point_conflict_from_superior_impl(const Point& point, Zone& zone
|
|||
if ( is_encroached_facet_refinable(*facet_it) )
|
||||
{
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
// CJTODO TEMP: not very clean
|
||||
Facet mirror = mirror_facet(*facet_it);
|
||||
auto f = boost::make_tuple(
|
||||
*facet_it, facet_it->first->get_erase_counter(),
|
||||
mirror, mirror.first->get_erase_counter());
|
||||
|
||||
// Unlock all
|
||||
unlock_all_thread_local_elements();
|
||||
|
||||
// CJTODO: what if it doesn's succeed???
|
||||
if( try_lock_element(*facet_it) )
|
||||
{
|
||||
// CJTODO: what if it doesn's succeed???
|
||||
if( !is_zombie(f) )
|
||||
try_to_refine_element(*facet_it, visitor);
|
||||
}
|
||||
try_to_refine_element(*facet_it, visitor);
|
||||
#else
|
||||
insert_encroached_facet_in_queue(*facet_it);
|
||||
#endif
|
||||
|
|
@ -639,21 +647,7 @@ test_point_conflict_from_superior_impl(const Point& point, Zone& zone
|
|||
if ( is_encroached_facet_refinable(*facet_it) )
|
||||
{
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
// CJTODO TEMP: not very clean
|
||||
Facet mirror = mirror_facet(*facet_it);
|
||||
auto f = boost::make_tuple(
|
||||
*facet_it, facet_it->first->get_erase_counter(),
|
||||
mirror, mirror.first->get_erase_counter());
|
||||
|
||||
unlock_all_thread_local_elements();
|
||||
|
||||
// CJTODO: what if it doesn's succeed???
|
||||
if( try_lock_element(*facet_it) )
|
||||
{
|
||||
// CJTODO: what if it doesn's succeed???
|
||||
if( !is_zombie(f) )
|
||||
try_to_refine_element(*facet_it, visitor);
|
||||
}
|
||||
try_to_refine_element(*facet_it, visitor);
|
||||
#else
|
||||
insert_encroached_facet_in_queue(*facet_it);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1015,11 +1015,19 @@ update_mesh(const Weighted_point& new_point,
|
|||
internal_facets.reserve(64);
|
||||
boundary_facets.reserve(64);
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
bool could_lock_zone = true;
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
tr_.find_conflicts(new_point,
|
||||
old_vertex->cell(),
|
||||
std::back_inserter(boundary_facets),
|
||||
std::back_inserter(deleted_cells),
|
||||
std::back_inserter(internal_facets));
|
||||
std::back_inserter(internal_facets)
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
, could_lock_zone
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
);
|
||||
|
||||
// Get some datas to restore mesh
|
||||
Boundary_facets_from_outside boundary_facets_from_outside =
|
||||
|
|
@ -1167,11 +1175,19 @@ check_pre_star(const Pre_star& pre_star,
|
|||
std::vector<Facet> boundary_facets;
|
||||
boundary_facets.reserve(64);
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
bool could_lock_zone = true;
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
tr_.find_conflicts(wp,
|
||||
vh->cell(),
|
||||
std::back_inserter(boundary_facets),
|
||||
CGAL::Emptyset_iterator(),
|
||||
CGAL::Emptyset_iterator());
|
||||
CGAL::Emptyset_iterator()
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
, could_lock_zone
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
);
|
||||
|
||||
const bool result = check_pre_star(pre_star,
|
||||
boundary_facets.begin(),
|
||||
|
|
|
|||
|
|
@ -49,18 +49,19 @@ namespace CGAL {
|
|||
Map multimap;
|
||||
Predicate test;
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
typedef tbb::enumerable_thread_specific< std::vector<std::pair<Quality, Element> > > LocalList;
|
||||
LocalList localList;
|
||||
bool m_addToTLSLists;
|
||||
typedef tbb::enumerable_thread_specific<
|
||||
std::deque<std::pair<Quality, Element> > > LocalList;
|
||||
LocalList m_local_lists;
|
||||
bool m_add_to_TLS_lists;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
explicit Filtered_multimap_container(bool addToTLSLists = false)
|
||||
: m_addToTLSLists(addToTLSLists) {}
|
||||
explicit Filtered_multimap_container(const Predicate &p, bool addToTLSLists=false)
|
||||
: test(p), m_addToTLSLists(addToTLSLists) {}
|
||||
explicit Filtered_multimap_container(bool add_to_TLS_lists = false)
|
||||
: m_add_to_TLS_lists(add_to_TLS_lists) {}
|
||||
explicit Filtered_multimap_container(const Predicate &p, bool add_to_TLS_lists=false)
|
||||
: test(p), m_add_to_TLS_lists(add_to_TLS_lists) {}
|
||||
#else
|
||||
Filtered_multimap_container() {}
|
||||
explicit Filtered_multimap_container(const Predicate &p)
|
||||
|
|
@ -69,6 +70,9 @@ namespace CGAL {
|
|||
|
||||
bool no_longer_element_to_refine_impl()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
size_t multimap_size = multimap.size();
|
||||
#endif
|
||||
bool is_empty = multimap.empty();
|
||||
while( !is_empty && !test(multimap.begin()->second) )
|
||||
{
|
||||
|
|
@ -99,21 +103,67 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
void addToTLSLists(bool add = true)
|
||||
void add_to_TLS_lists_impl(bool add = true)
|
||||
{
|
||||
m_addToTLSLists = add;
|
||||
m_add_to_TLS_lists = add;
|
||||
}
|
||||
|
||||
void spliceLocalLists()
|
||||
void splice_local_lists_impl()
|
||||
{
|
||||
for( LocalList::iterator it_list = localList.begin() ;
|
||||
it_list != localList.end() ;
|
||||
for( LocalList::iterator it_list = m_local_lists.begin() ;
|
||||
it_list != m_local_lists.end() ;
|
||||
++it_list )
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
size_t multimap_size = multimap.size();
|
||||
size_t local_list_size = it_list->size();
|
||||
#endif
|
||||
multimap.insert(it_list->begin(), it_list->end());
|
||||
it_list->clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool no_longer_local_element_to_refine_impl()
|
||||
{
|
||||
bool is_empty = m_local_lists.local().empty();
|
||||
while( !is_empty && !test(m_local_lists.local().front().second) )
|
||||
{
|
||||
pop_next_local_element_impl();
|
||||
is_empty = m_local_lists.local().empty();
|
||||
}
|
||||
return is_empty;
|
||||
}
|
||||
|
||||
// Warning: no_longer_local_element_to_refine_impl must have been called
|
||||
// just before calling get_next_local_element_impl
|
||||
// (successive calls to "get_next_local_element_impl" are not allowed)
|
||||
Element get_next_local_element_impl()
|
||||
{
|
||||
CGAL_assertion(!m_local_lists.local().empty());
|
||||
// CJTODO BUG: add this? It shouldn't be necessary as user
|
||||
// is supposed to call "no_longer_element_to_refine_impl" first
|
||||
/*while( !test(multimap.front()) )
|
||||
{
|
||||
multimap.pop_front();
|
||||
}*/
|
||||
return m_local_lists.local().front().second;
|
||||
}
|
||||
|
||||
// Warning: no_longer_local_element_to_refine_impl must have been called
|
||||
// just before calling get_next_local_raw_element_impl
|
||||
// (successive calls to "get_next_local_raw_element_impl" are not allowed)
|
||||
value_type get_next_local_raw_element_impl()
|
||||
{
|
||||
CGAL_assertion(!m_local_lists.local().empty());
|
||||
return m_local_lists.local().front();
|
||||
}
|
||||
|
||||
void pop_next_local_element_impl()
|
||||
{
|
||||
// Erase last element
|
||||
m_local_lists.local().pop_front();
|
||||
}
|
||||
#endif
|
||||
|
||||
void pop_next_element_impl()
|
||||
|
|
@ -138,8 +188,8 @@ namespace CGAL {
|
|||
}
|
||||
|
||||
// Warning: no_longer_element_to_refine_impl must have been called
|
||||
// just before calling get_next_element_impl
|
||||
// (successive calls to "get_next_element_impl" are not allowed)
|
||||
// just before calling get_next_raw_element_impl
|
||||
// (successive calls to "get_next_raw_element_impl" are not allowed)
|
||||
value_type get_next_raw_element_impl()
|
||||
{
|
||||
CGAL_assertion(!multimap.empty());
|
||||
|
|
@ -149,8 +199,8 @@ namespace CGAL {
|
|||
void insert_raw_element(const value_type &re)
|
||||
{
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
if (m_addToTLSLists)
|
||||
localList.local().push_back(re);
|
||||
if (m_add_to_TLS_lists)
|
||||
m_local_lists.local().push_back(re);
|
||||
else
|
||||
multimap.insert(re);
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) 1999-2005 INRIA Sophia-Antipolis (France).
|
||||
// Copyright (c) 2012 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
|
|
@ -64,50 +64,9 @@ public:
|
|||
bool success = true;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
// Lock the element area on the grid
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
Vertex_handle vh = vertex(iVertex);
|
||||
//if (vh != infinite_vertex()) // CJTODO: à tester?
|
||||
std::pair<bool, int> r = g_lock_grid.try_lock(vh->point());
|
||||
success = r.first;
|
||||
}
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
success = m_mutex.try_lock();
|
||||
if (success)
|
||||
g_tls_locked_cells.local().push_back(std::make_pair(this, m_erase_counter));
|
||||
# endif
|
||||
|
||||
return success;
|
||||
}
|
||||
/*
|
||||
bool try_lock(bool unlock_if_failure = false)
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
int locked_vertices[4];
|
||||
// Lock the element area on the grid
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
Vertex_handle vh = vertex(iVertex);
|
||||
//if (vh != infinite_vertex()) // CJTODO: à tester?
|
||||
std::pair<bool, int> r = g_lock_grid.try_lock(vh->point());
|
||||
success = r.first;
|
||||
if (unlock_if_failure)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
locked_vertices[iVertex] = r.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unlock elements we locked
|
||||
for (int i = 0 ; i < iVertex ; ++i)
|
||||
g_lock_grid.unlock(locked_vertices[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cerr << "Error: Triangulation_lazy_ds_cell_base_3::try_lock() "
|
||||
"should not be called. Use Triangulation_3::try_lock_element() instead."
|
||||
<< std::endl;
|
||||
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
success = m_mutex.try_lock();
|
||||
|
|
@ -117,7 +76,6 @@ public:
|
|||
|
||||
return success;
|
||||
}
|
||||
*/
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK
|
||||
void lock()
|
||||
|
|
@ -130,24 +88,6 @@ public:
|
|||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
#elif defined(CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING)
|
||||
// CJTODO: Warning: this lock is not "atomic", it locks
|
||||
// one vertex after the other
|
||||
void lock()
|
||||
{
|
||||
// Active wait
|
||||
while (!try_lock())
|
||||
tbb::this_tbb_thread::yield();
|
||||
}
|
||||
|
||||
void unlock()
|
||||
{
|
||||
for (int iVertex = 0 ; iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
Vertex_handle vh = vertex(iVertex);
|
||||
g_lock_grid.unlock(vh->point());
|
||||
}
|
||||
}
|
||||
# endif
|
||||
|
||||
typedef tbb::atomic<unsigned int> Erase_counter_type;
|
||||
|
|
|
|||
|
|
@ -519,6 +519,60 @@ public:
|
|||
# endif // no CGAL_T3_STRUCTURAL_FILTERING_MAX_VISITED_CELLS
|
||||
|
||||
|
||||
// LOCKS (CONCURRENCY)
|
||||
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
bool try_lock_element(Cell_handle cell_handle, int lock_radius = 0) const
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
// Lock the element area on the grid
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
Vertex_handle vh = cell_handle->vertex(iVertex);
|
||||
// We do not lock the infinite vertex
|
||||
//if (!is_infinite(vh))
|
||||
{
|
||||
success = g_lock_grid.try_lock(vh->point(), lock_radius).first;
|
||||
}
|
||||
}
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
success = cell_handle->try_lock();
|
||||
# endif
|
||||
|
||||
return success;
|
||||
}
|
||||
bool try_lock_element(const Facet &facet, int lock_radius = 0) const
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
# ifdef CGAL_MESH_3_LOCKING_STRATEGY_SIMPLE_GRID_LOCKING
|
||||
// Lock the element area on the grid
|
||||
Cell_handle cell = facet.first;
|
||||
for (int iVertex = 0 ; success && iVertex < 4 ; ++iVertex)
|
||||
{
|
||||
if (iVertex != facet.second)
|
||||
{
|
||||
Vertex_handle vh = cell->vertex(iVertex);
|
||||
// We do not lock the infinite vertex
|
||||
//if (!is_infinite(vh))
|
||||
{
|
||||
success = g_lock_grid.try_lock(vh->point(), lock_radius).first;
|
||||
}
|
||||
}
|
||||
}
|
||||
# elif defined(CGAL_MESH_3_LOCKING_STRATEGY_CELL_LOCK)
|
||||
success = facet.first->try_lock(); // CJTODO: we lock the cell => stupid?
|
||||
# endif
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
|
||||
protected:
|
||||
Cell_handle
|
||||
inexact_locate(const Point& p,
|
||||
|
|
@ -864,7 +918,8 @@ protected:
|
|||
|
||||
template < class InputIterator >
|
||||
bool infinite_vertex_in_range(InputIterator first, InputIterator beyond) const;
|
||||
|
||||
|
||||
|
||||
// - c is the current cell, which must be in conflict.
|
||||
// - tester is the function object that tests if a cell is in conflict.
|
||||
template <
|
||||
|
|
@ -901,7 +956,7 @@ protected:
|
|||
// CJTODO: useless?
|
||||
if (p_could_lock_zone)
|
||||
{
|
||||
if (!d->try_lock())
|
||||
if (!try_lock_element(d))
|
||||
{
|
||||
*p_could_lock_zone = false;
|
||||
return it;
|
||||
|
|
@ -911,14 +966,12 @@ protected:
|
|||
// To store the bouldary cells, in case we need to rollback
|
||||
// CJTODO: make it static TLS (for performance)
|
||||
// CJTODO: useless car déjà fait dans Regular_tri_3::find_conflicts?
|
||||
std::vector<Cell_handle> marked_cells;
|
||||
|
||||
#endif // CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
|
||||
cell_stack.push(d);
|
||||
d->tds_data().mark_in_conflict();
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
marked_cells.push_back(d);
|
||||
#endif
|
||||
*it.second++ = d;
|
||||
|
||||
|
|
@ -937,15 +990,9 @@ protected:
|
|||
defined(CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS)
|
||||
if (p_could_lock_zone)
|
||||
{
|
||||
if (!test->try_lock())
|
||||
if (!try_lock_element(test))
|
||||
{
|
||||
*p_could_lock_zone = false;
|
||||
// Rollback
|
||||
// CJTODO: is it really necessary?
|
||||
std::vector<Cell_handle>::iterator it_marked_cell = marked_cells.begin();
|
||||
std::vector<Cell_handle>::iterator it_marked_cell_end = marked_cells.end();
|
||||
for ( ; it_marked_cell != it_marked_cell_end ; ++it_marked_cell)
|
||||
(*it_marked_cell)->tds_data().clear();
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
|
@ -965,15 +1012,9 @@ protected:
|
|||
!defined(CGAL_MESH_3_CONCURRENT_REFINEMENT_LOCK_ADJ_CELLS)
|
||||
if (p_could_lock_zone)
|
||||
{
|
||||
if (!test->try_lock())
|
||||
if (!try_lock_element(test))
|
||||
{
|
||||
*p_could_lock_zone = false;
|
||||
// Rollback
|
||||
// CJTODO: is it really necessary?
|
||||
std::vector<Cell_handle>::iterator it_marked_cell = marked_cells.begin();
|
||||
std::vector<Cell_handle>::iterator it_marked_cell_end = marked_cells.end();
|
||||
for ( ; it_marked_cell != it_marked_cell_end ; ++it_marked_cell)
|
||||
(*it_marked_cell)->tds_data().clear();
|
||||
// Unlock
|
||||
return it;
|
||||
}
|
||||
|
|
@ -986,17 +1027,11 @@ protected:
|
|||
|
||||
cell_stack.push(test);
|
||||
test->tds_data().mark_in_conflict();
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
marked_cells.push_back(test);
|
||||
#endif
|
||||
*it.second++ = test;
|
||||
continue;
|
||||
}
|
||||
|
||||
test->tds_data().mark_on_boundary();
|
||||
#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
marked_cells.push_back(test);
|
||||
#endif
|
||||
}
|
||||
*it.first++ = Facet(c, i);
|
||||
}
|
||||
|
|
@ -2056,11 +2091,9 @@ exact_locate(const Point & p, Locate_type & lt, int & li, int & lj,
|
|||
{
|
||||
// CJTODO: useless? already locked buy Mesher_level?
|
||||
//c->lock(); // WARNING: not atomic! => DEADLOCKS?
|
||||
if (!c->try_lock())
|
||||
if (!try_lock_element(c))
|
||||
{
|
||||
*p_could_lock_zone = false;
|
||||
// CJTODO: WHY DOES IT CRASH IF WE UNLOCK HERE??? (TEST IT)
|
||||
//g_lock_grid.unlock_all_tls_locked_cells();
|
||||
return Cell_handle();
|
||||
}
|
||||
}
|
||||
|
|
@ -2129,11 +2162,9 @@ exact_locate(const Point & p, Locate_type & lt, int & li, int & lj,
|
|||
{
|
||||
//previous->unlock(); CJTODO: On en déverrouille TROP, non ?
|
||||
//c->lock(); // WARNING: not atomic! => DEADLOCKS?
|
||||
if (!c->try_lock())
|
||||
if (!try_lock_element(c))
|
||||
{
|
||||
*p_could_lock_zone = false;
|
||||
// CJTODO: WHY DOES IT CRASH IF WE UNLOCK HERE??? (TEST IT)
|
||||
//g_lock_grid.unlock_all_tls_locked_cells();
|
||||
return Cell_handle();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,11 +25,19 @@
|
|||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
#include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
# include <CGAL/Triangulation_lazy_ds_cell_base_3.h>
|
||||
#else
|
||||
# include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
template < typename GT, typename Cb = Triangulation_lazy_ds_cell_base_3<> >
|
||||
#else
|
||||
template < typename GT, typename Cb = Triangulation_ds_cell_base_3<> >
|
||||
#endif
|
||||
class Triangulation_cell_base_3
|
||||
: public Cb
|
||||
{
|
||||
|
|
|
|||
|
|
@ -26,11 +26,19 @@
|
|||
|
||||
#include <CGAL/basic.h>
|
||||
#include <CGAL/triangulation_assertions.h>
|
||||
#include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
# include <CGAL/Triangulation_lazy_ds_cell_base_3.h>
|
||||
#else
|
||||
# include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
template < typename GT, typename Cb = Triangulation_lazy_ds_cell_base_3<> >
|
||||
#else
|
||||
template < typename GT, typename Cb = Triangulation_ds_cell_base_3<> >
|
||||
#endif
|
||||
class Triangulation_cell_base_with_circumcenter_3
|
||||
: public Cb
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,7 +45,11 @@
|
|||
#include <CGAL/Compact_container.h>
|
||||
#endif
|
||||
|
||||
#include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
# include <CGAL/Triangulation_lazy_ds_cell_base_3.h>
|
||||
#else
|
||||
# include <CGAL/Triangulation_ds_cell_base_3.h>
|
||||
#endif
|
||||
#include <CGAL/Triangulation_ds_vertex_base_3.h>
|
||||
#include <CGAL/Triangulation_simplex_3.h>
|
||||
|
||||
|
|
@ -66,7 +70,11 @@ namespace CGAL {
|
|||
// TODO : noms : Vb != Vertex_base : clarifier.
|
||||
|
||||
template < class Vb = Triangulation_ds_vertex_base_3<>,
|
||||
#ifdef CGAL_MESH_3_LAZY_REFINEMENT_QUEUE
|
||||
class Cb = Triangulation_lazy_ds_cell_base_3<> >
|
||||
#else
|
||||
class Cb = Triangulation_ds_cell_base_3<> >
|
||||
#endif
|
||||
class Triangulation_data_structure_3
|
||||
: public Triangulation_utils_3
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,6 +23,14 @@
|
|||
#include <CGAL/basic.h>
|
||||
#include <CGAL/internal/Dummy_tds_3.h>
|
||||
|
||||
// CJTODO TEMP TEST
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
//# ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
//# include <tbb/atomic.h>
|
||||
//# endif
|
||||
extern bool g_is_set_cell_active;
|
||||
#endif
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template < typename TDS = void >
|
||||
|
|
@ -46,7 +54,15 @@ public:
|
|||
{ return _c; }
|
||||
|
||||
void set_cell(Cell_handle c)
|
||||
{ _c = c; }
|
||||
{
|
||||
// CJTODO TEMP TEST
|
||||
#ifdef CONCURRENT_MESH_3
|
||||
if (g_is_set_cell_active)
|
||||
_c = c;
|
||||
#else
|
||||
_c = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
// the following trivial is_valid allows
|
||||
// the user of derived cell base classes
|
||||
|
|
@ -63,7 +79,12 @@ public:
|
|||
{ return _c.for_compact_container(); }
|
||||
|
||||
private:
|
||||
// CJTODO TEMP
|
||||
//#ifdef CGAL_MESH_3_CONCURRENT_REFINEMENT
|
||||
// tbb::atomic<Cell_handle> _c;
|
||||
//#else
|
||||
Cell_handle _c;
|
||||
//#endif
|
||||
};
|
||||
|
||||
template < class TDS >
|
||||
|
|
|
|||
Loading…
Reference in New Issue