mirror of https://github.com/CGAL/cgal
fix the concurrent compact container with timestamps
This commit is contained in:
parent
eb0da467ed
commit
5853673267
|
|
@ -220,6 +220,10 @@ class Compact_container
|
||||||
CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE>
|
CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE>
|
||||||
>::type Increment_policy;
|
>::type Increment_policy;
|
||||||
typedef TimeStamper_ Ts;
|
typedef TimeStamper_ Ts;
|
||||||
|
|
||||||
|
template <typename U> using EraseCounterStrategy =
|
||||||
|
internal::Erase_counter_strategy<internal::has_increment_erase_counter<U>::value>;
|
||||||
|
|
||||||
typedef Compact_container <T, Al, Ip, Ts> Self;
|
typedef Compact_container <T, Al, Ip, Ts> Self;
|
||||||
typedef Compact_container_traits <T> Traits;
|
typedef Compact_container_traits <T> Traits;
|
||||||
public:
|
public:
|
||||||
|
|
@ -354,7 +358,7 @@ public:
|
||||||
return all_items[block_number].first[index_in_block];
|
return all_items[block_number].first[index_in_block];
|
||||||
}
|
}
|
||||||
|
|
||||||
friend void swap(Compact_container& a, Compact_container b) {
|
friend void swap(Compact_container& a, Compact_container b) noexcept {
|
||||||
a.swap(b);
|
a.swap(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -390,22 +394,16 @@ public:
|
||||||
// (just forward the arguments to the constructor, to optimize a copy).
|
// (just forward the arguments to the constructor, to optimize a copy).
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
iterator
|
iterator
|
||||||
emplace(const Args&... args)
|
emplace(Args&&... args)
|
||||||
{
|
{
|
||||||
if (free_list == nullptr)
|
if (free_list == nullptr)
|
||||||
allocate_new_block();
|
allocate_new_block();
|
||||||
|
|
||||||
pointer ret = free_list;
|
pointer ret = free_list;
|
||||||
free_list = clean_pointee(ret);
|
free_list = clean_pointee(ret);
|
||||||
std::size_t ts;
|
const auto ts = Time_stamper::time_stamp(ret);
|
||||||
CGAL_USE(ts);
|
std::allocator_traits<allocator_type>::construct(alloc, ret, std::forward<Args>(args)...);
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
Time_stamper::restore_timestamp(ret, ts);
|
||||||
ts = ret->time_stamp();
|
|
||||||
}
|
|
||||||
new (ret) value_type(args...);
|
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
|
||||||
ret->set_time_stamp(ts);
|
|
||||||
}
|
|
||||||
Time_stamper::set_time_stamp(ret, time_stamp);
|
Time_stamper::set_time_stamp(ret, time_stamp);
|
||||||
CGAL_assertion(type(ret) == USED);
|
CGAL_assertion(type(ret) == USED);
|
||||||
++size_;
|
++size_;
|
||||||
|
|
@ -414,24 +412,7 @@ public:
|
||||||
|
|
||||||
iterator insert(const T &t)
|
iterator insert(const T &t)
|
||||||
{
|
{
|
||||||
if (free_list == nullptr)
|
return emplace(t);
|
||||||
allocate_new_block();
|
|
||||||
|
|
||||||
pointer ret = free_list;
|
|
||||||
free_list = clean_pointee(ret);
|
|
||||||
std::size_t ts;
|
|
||||||
CGAL_USE(ts);
|
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
|
||||||
ts = ret->time_stamp();
|
|
||||||
}
|
|
||||||
std::allocator_traits<allocator_type>::construct(alloc, ret, t);
|
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
|
||||||
ret->set_time_stamp(ts);
|
|
||||||
}
|
|
||||||
Time_stamper::set_time_stamp(ret, time_stamp);
|
|
||||||
CGAL_assertion(type(ret) == USED);
|
|
||||||
++size_;
|
|
||||||
return iterator(ret, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class InputIterator >
|
template < class InputIterator >
|
||||||
|
|
@ -450,22 +431,14 @@ public:
|
||||||
|
|
||||||
void erase(iterator x)
|
void erase(iterator x)
|
||||||
{
|
{
|
||||||
typedef internal::Erase_counter_strategy<
|
auto ptr = &*x;
|
||||||
internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
CGAL_precondition(type(ptr) == USED);
|
||||||
|
EraseCounterStrategy<T>::increment_erase_counter(*x);
|
||||||
|
const auto ts = Time_stamper::time_stamp(ptr);
|
||||||
|
std::allocator_traits<allocator_type>::destroy(alloc, ptr);
|
||||||
|
Time_stamper::restore_timestamp(ptr, ts);
|
||||||
|
|
||||||
CGAL_precondition(type(&*x) == USED);
|
put_on_free_list(ptr);
|
||||||
EraseCounterStrategy::increment_erase_counter(*x);
|
|
||||||
std::size_t ts;
|
|
||||||
CGAL_USE(ts);
|
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
|
||||||
ts = x->time_stamp();
|
|
||||||
}
|
|
||||||
std::allocator_traits<allocator_type>::destroy(alloc, &*x);
|
|
||||||
if constexpr (Time_stamper::has_timestamp) {
|
|
||||||
x->set_time_stamp(ts);
|
|
||||||
}
|
|
||||||
|
|
||||||
put_on_free_list(&*x);
|
|
||||||
--size_;
|
--size_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -697,7 +670,7 @@ public:
|
||||||
static bool is_begin_or_end(const_pointer ptr)
|
static bool is_begin_or_end(const_pointer ptr)
|
||||||
{ return type(ptr)==START_END; }
|
{ return type(ptr)==START_END; }
|
||||||
|
|
||||||
void swap(Self &c)
|
void swap(Self &c) noexcept
|
||||||
{
|
{
|
||||||
std::swap(alloc, c.alloc);
|
std::swap(alloc, c.alloc);
|
||||||
std::swap(capacity_, c.capacity_);
|
std::swap(capacity_, c.capacity_);
|
||||||
|
|
@ -805,9 +778,6 @@ void Compact_container<T, Allocator, Increment_policy, TimeStamper>::clear()
|
||||||
template < class T, class Allocator, class Increment_policy, class TimeStamper >
|
template < class T, class Allocator, class Increment_policy, class TimeStamper >
|
||||||
void Compact_container<T, Allocator, Increment_policy, TimeStamper>::allocate_new_block()
|
void Compact_container<T, Allocator, Increment_policy, TimeStamper>::allocate_new_block()
|
||||||
{
|
{
|
||||||
typedef internal::Erase_counter_strategy<
|
|
||||||
internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
|
||||||
|
|
||||||
pointer new_block = alloc.allocate(block_size + 2);
|
pointer new_block = alloc.allocate(block_size + 2);
|
||||||
all_items.push_back(std::make_pair(new_block, block_size + 2));
|
all_items.push_back(std::make_pair(new_block, block_size + 2));
|
||||||
capacity_ += block_size;
|
capacity_ += block_size;
|
||||||
|
|
@ -816,7 +786,7 @@ void Compact_container<T, Allocator, Increment_policy, TimeStamper>::allocate_ne
|
||||||
// will correspond to the iterator order...
|
// will correspond to the iterator order...
|
||||||
for (size_type i = block_size; i >= 1; --i)
|
for (size_type i = block_size; i >= 1; --i)
|
||||||
{
|
{
|
||||||
EraseCounterStrategy::set_erase_counter(*(new_block + i), 0);
|
EraseCounterStrategy<T>::set_erase_counter(*(new_block + i), 0);
|
||||||
Time_stamper::initialize_time_stamp(new_block + i);
|
Time_stamper::initialize_time_stamp(new_block + i);
|
||||||
put_on_free_list(new_block + i);
|
put_on_free_list(new_block + i);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,9 @@ class Concurrent_compact_container
|
||||||
typedef Concurrent_compact_container <T, Al> Self;
|
typedef Concurrent_compact_container <T, Al> Self;
|
||||||
typedef Concurrent_compact_container_traits <T> Traits;
|
typedef Concurrent_compact_container_traits <T> Traits;
|
||||||
|
|
||||||
|
template <typename U> using EraseCounterStrategy =
|
||||||
|
internal::Erase_counter_strategy<internal::has_increment_erase_counter<U>::value>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef CGAL::Time_stamper_impl<T> Time_stamper;
|
typedef CGAL::Time_stamper_impl<T> Time_stamper;
|
||||||
typedef Time_stamper Time_stamper_impl; // backward compatibility
|
typedef Time_stamper Time_stamper_impl; // backward compatibility
|
||||||
|
|
@ -344,28 +347,21 @@ public:
|
||||||
// (just forward the arguments to the constructor, to optimize a copy).
|
// (just forward the arguments to the constructor, to optimize a copy).
|
||||||
template < typename... Args >
|
template < typename... Args >
|
||||||
iterator
|
iterator
|
||||||
emplace(const Args&... args)
|
emplace(Args&&... args)
|
||||||
{
|
{
|
||||||
typedef CCC_internal::Erase_counter_strategy<
|
|
||||||
CCC_internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
|
||||||
FreeList * fl = get_free_list();
|
FreeList * fl = get_free_list();
|
||||||
pointer ret = init_insert(fl);
|
pointer ret = init_insert(fl);
|
||||||
auto erase_counter = EraseCounterStrategy::erase_counter(*ret);;
|
auto erase_counter = EraseCounterStrategy<T>::erase_counter(*ret);
|
||||||
new (ret) value_type(args...);
|
const auto ts = Time_stamper::time_stamp(ret);
|
||||||
EraseCounterStrategy::set_erase_counter(*ret, erase_counter);
|
std::allocator_traits<allocator_type>::construct(m_alloc, ret, std::forward<Args>(args)...);
|
||||||
|
Time_stamper::restore_timestamp(ret, ts);
|
||||||
|
EraseCounterStrategy<T>::set_erase_counter(*ret, erase_counter);
|
||||||
return finalize_insert(ret, fl);
|
return finalize_insert(ret, fl);
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator insert(const T &t)
|
iterator insert(const T &t)
|
||||||
{
|
{
|
||||||
typedef CCC_internal::Erase_counter_strategy<
|
return emplace(t);
|
||||||
CCC_internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
|
||||||
FreeList * fl = get_free_list();
|
|
||||||
pointer ret = init_insert(fl);
|
|
||||||
auto erase_counter = EraseCounterStrategy::erase_counter(*ret);;
|
|
||||||
std::allocator_traits<allocator_type>::construct(m_alloc, ret, t);
|
|
||||||
EraseCounterStrategy::set_erase_counter(*ret, erase_counter);
|
|
||||||
return finalize_insert(ret, fl);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template < class InputIterator >
|
template < class InputIterator >
|
||||||
|
|
@ -385,13 +381,13 @@ public:
|
||||||
private:
|
private:
|
||||||
void erase(iterator x, FreeList * fl)
|
void erase(iterator x, FreeList * fl)
|
||||||
{
|
{
|
||||||
typedef CCC_internal::Erase_counter_strategy<
|
|
||||||
CCC_internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
|
||||||
|
|
||||||
CGAL_precondition(type(x) == USED);
|
CGAL_precondition(type(x) == USED);
|
||||||
EraseCounterStrategy::increment_erase_counter(*x);
|
EraseCounterStrategy<T>::increment_erase_counter(*x);
|
||||||
|
|
||||||
|
auto ptr = &*x;
|
||||||
|
const auto ts = Time_stamper::time_stamp(ptr);
|
||||||
std::allocator_traits<allocator_type>::destroy(m_alloc, &*x);
|
std::allocator_traits<allocator_type>::destroy(m_alloc, &*x);
|
||||||
|
Time_stamper::restore_timestamp(ptr, ts);
|
||||||
|
|
||||||
put_on_free_list(&*x, fl);
|
put_on_free_list(&*x, fl);
|
||||||
}
|
}
|
||||||
|
|
@ -778,9 +774,6 @@ template < class T, class Allocator >
|
||||||
void Concurrent_compact_container<T, Allocator>::
|
void Concurrent_compact_container<T, Allocator>::
|
||||||
allocate_new_block(FreeList * fl)
|
allocate_new_block(FreeList * fl)
|
||||||
{
|
{
|
||||||
typedef CCC_internal::Erase_counter_strategy<
|
|
||||||
CCC_internal::has_increment_erase_counter<T>::value> EraseCounterStrategy;
|
|
||||||
|
|
||||||
size_type old_block_size;
|
size_type old_block_size;
|
||||||
pointer new_block;
|
pointer new_block;
|
||||||
|
|
||||||
|
|
@ -818,7 +811,7 @@ void Concurrent_compact_container<T, Allocator>::
|
||||||
// will correspond to the iterator order...
|
// will correspond to the iterator order...
|
||||||
for (size_type i = old_block_size; i >= 1; --i)
|
for (size_type i = old_block_size; i >= 1; --i)
|
||||||
{
|
{
|
||||||
EraseCounterStrategy::set_erase_counter(*(new_block + i), 0);
|
EraseCounterStrategy<T>::set_erase_counter(*(new_block + i), 0);
|
||||||
Time_stamper::initialize_time_stamp(new_block + i);
|
Time_stamper::initialize_time_stamp(new_block + i);
|
||||||
put_on_free_list(new_block + i, fl);
|
put_on_free_list(new_block + i, fl);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,13 +30,17 @@ struct Time_stamper
|
||||||
{
|
{
|
||||||
static constexpr bool has_timestamp = true;
|
static constexpr bool has_timestamp = true;
|
||||||
|
|
||||||
|
static bool is_valid(const T* pt) {
|
||||||
|
return pt != nullptr && pt->time_stamp() != std::size_t(-2);
|
||||||
|
}
|
||||||
|
|
||||||
static void initialize_time_stamp(T* pt) {
|
static void initialize_time_stamp(T* pt) {
|
||||||
pt->set_time_stamp(std::size_t(-1));
|
pt->set_time_stamp(std::size_t(-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename time_stamp_t>
|
template <typename time_stamp_t>
|
||||||
static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) {
|
static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) {
|
||||||
CGAL_assertion(pt->time_stamp() != std::size_t(-2));
|
CGAL_assertion(is_valid(pt));
|
||||||
if(pt->time_stamp() == std::size_t(-1)) {
|
if(pt->time_stamp() == std::size_t(-1)) {
|
||||||
const std::size_t new_ts = time_stamp_++;
|
const std::size_t new_ts = time_stamp_++;
|
||||||
pt->set_time_stamp(new_ts);
|
pt->set_time_stamp(new_ts);
|
||||||
|
|
@ -64,13 +68,18 @@ struct Time_stamper
|
||||||
|
|
||||||
static std::size_t time_stamp(const T* pt)
|
static std::size_t time_stamp(const T* pt)
|
||||||
{
|
{
|
||||||
CGAL_assertion(pt == nullptr || pt->time_stamp() != std::size_t(-2));
|
CGAL_assertion(is_valid(pt));
|
||||||
if(pt == nullptr){
|
if(pt == nullptr){
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
return pt->time_stamp();
|
return pt->time_stamp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void restore_timestamp(T* pt, std::size_t ts)
|
||||||
|
{
|
||||||
|
pt->set_time_stamp(ts);
|
||||||
|
}
|
||||||
|
|
||||||
static auto display_id(const T* pt, int offset = 0)
|
static auto display_id(const T* pt, int offset = 0)
|
||||||
{
|
{
|
||||||
if(pt == nullptr)
|
if(pt == nullptr)
|
||||||
|
|
@ -80,7 +89,7 @@ struct Time_stamper
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::size_t hash_value(const T* p) {
|
static std::size_t hash_value(const T* p) {
|
||||||
CGAL_assertion(p == nullptr || p->time_stamp() != std::size_t(-2));
|
CGAL_assertion(is_valid(p));
|
||||||
if(nullptr == p)
|
if(nullptr == p)
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
else
|
else
|
||||||
|
|
@ -116,6 +125,10 @@ public:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void restore_timestamp(T*, std::size_t)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static auto display_id(const T* pt, int)
|
static auto display_id(const T* pt, int)
|
||||||
{
|
{
|
||||||
return static_cast<const void*>(pt);
|
return static_cast<const void*>(pt);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue