Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
chainbase::undo_index< T, Allocator, Indices > Class Template Reference

#include <undo_index.hpp>

Classes

struct  delta
 
struct  node
 
struct  old_node
 
class  removed_nodes_tracker
 
class  session
 
struct  undo_state
 

Public Types

using id_type = std::decay_t<decltype(std::declval<T>().id)>
 
using value_type = T
 
using allocator_type = Allocator
 
using indices_type = std::tuple<set_impl<node, Indices>...>
 
using index0_set_type = std::tuple_element_t<0, indices_type>
 
using alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<node>
 
using index0_type = boost::mp11::mp_first<boost::mp11::mp_list<Indices...>>
 
using id_pointer = id_type*
 
using pointer = value_type*
 
using const_iterator = typename index0_set_type::const_iterator
 

Public Member Functions

 undo_index ()=default
 
 undo_index (const Allocator &a)
 
 ~undo_index ()
 
void validate () const
 
template<typename Constructor >
const value_typeemplace (Constructor &&c)
 
template<typename Modifier >
void modify (const value_type &obj, Modifier &&m)
 
auto track_removed ()
 
void remove (const value_type &obj) noexcept
 
template<typename CompatibleKey >
const value_typefind (CompatibleKey &&key) const
 
template<typename CompatibleKey >
const value_typeget (CompatibleKey &&key) const
 
void remove_object (int64_t id)
 
int64_t revision () const
 
session start_undo_session (bool enabled)
 
void set_revision (uint64_t revision)
 
std::pair< int64_t, int64_tundo_stack_revision_range () const
 
void commit (int64_t revision) noexcept
 
const undo_indexindices () const
 
template<typename Tag >
const auto & get () const
 
template<int N>
const auto & get () const
 
std::size_t size () const
 
bool empty () const
 
template<typename Tag , typename Iter >
auto project (Iter iter) const
 
template<int N, typename Iter >
auto project (Iter iter) const
 
bool has_undo_session () const
 
delta last_undo_session () const
 
auto begin () const
 
auto end () const
 
void undo_all ()
 
void undo () noexcept
 
void squash () noexcept
 
void squash_fast () noexcept
 
void squash_and_compress () noexcept
 
void compress_last_undo_session () noexcept
 

Static Public Attributes

static constexpr int erased_flag = 2
 

Detailed Description

template<typename T, typename Allocator, typename... Indices>
class chainbase::undo_index< T, Allocator, Indices >

Definition at line 235 of file undo_index.hpp.

Member Typedef Documentation

◆ alloc_traits

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::alloc_traits = typename std::allocator_traits<Allocator>::template rebind_traits<node>

Definition at line 269 of file undo_index.hpp.

◆ allocator_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::allocator_type = Allocator

Definition at line 239 of file undo_index.hpp.

◆ const_iterator

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::const_iterator = typename index0_set_type::const_iterator

Definition at line 285 of file undo_index.hpp.

◆ id_pointer

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::id_pointer = id_type*

Definition at line 283 of file undo_index.hpp.

◆ id_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::id_type = std::decay_t<decltype(std::declval<T>().id)>

Definition at line 237 of file undo_index.hpp.

◆ index0_set_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::index0_set_type = std::tuple_element_t<0, indices_type>

Definition at line 268 of file undo_index.hpp.

◆ index0_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::index0_type = boost::mp11::mp_first<boost::mp11::mp_list<Indices...>>

Definition at line 273 of file undo_index.hpp.

◆ indices_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::indices_type = std::tuple<set_impl<node, Indices>...>

Definition at line 266 of file undo_index.hpp.

◆ pointer

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::pointer = value_type*

Definition at line 284 of file undo_index.hpp.

◆ value_type

template<typename T , typename Allocator , typename... Indices>
using chainbase::undo_index< T, Allocator, Indices >::value_type = T

Definition at line 238 of file undo_index.hpp.

Constructor & Destructor Documentation

◆ undo_index() [1/2]

template<typename T , typename Allocator , typename... Indices>
chainbase::undo_index< T, Allocator, Indices >::undo_index ( )
default

◆ undo_index() [2/2]

template<typename T , typename Allocator , typename... Indices>
chainbase::undo_index< T, Allocator, Indices >::undo_index ( const Allocator & a)
inlineexplicit

Definition at line 244 of file undo_index.hpp.

244: _undo_stack{a}, _allocator{a}, _old_values_allocator{a} {}
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181

◆ ~undo_index()

template<typename T , typename Allocator , typename... Indices>
chainbase::undo_index< T, Allocator, Indices >::~undo_index ( )
inline

Definition at line 245 of file undo_index.hpp.

245 {
246 dispose_undo();
247 clear_impl<1>();
248 std::get<0>(_indices).clear_and_dispose([&](pointer p){ dispose_node(*p); });
249 }
const mie::Vuint & p
Definition bn.cpp:27

Member Function Documentation

◆ begin()

template<typename T , typename Allocator , typename... Indices>
auto chainbase::undo_index< T, Allocator, Indices >::begin ( ) const
inline

Definition at line 600 of file undo_index.hpp.

600{ return get<0>().begin(); }
const auto & get() const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ commit()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::commit ( int64_t revision)
inlinenoexcept

Discards all undo history prior to revision

Definition at line 540 of file undo_index.hpp.

540 {
541 revision = std::min(revision, _revision);
542 if (revision == _revision) {
543 dispose_undo();
544 _undo_stack.clear();
545 } else if( static_cast<uint64_t>(_revision - revision) < _undo_stack.size() ) {
546 auto iter = _undo_stack.begin() + (_undo_stack.size() - (_revision - revision));
547 dispose(get_old_values_end(*iter), get_removed_values_end(*iter));
548 _undo_stack.erase(_undo_stack.begin(), iter);
549 }
550 }
int64_t revision() const
unsigned __int64 uint64_t
Definition stdint.h:136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ compress_last_undo_session()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::compress_last_undo_session ( )
inlinenoexcept

Definition at line 676 of file undo_index.hpp.

676 {
677 compress_impl(_undo_stack.back());
678 }
Here is the caller graph for this function:

◆ emplace()

template<typename T , typename Allocator , typename... Indices>
template<typename Constructor >
const value_type & chainbase::undo_index< T, Allocator, Indices >::emplace ( Constructor && c)
inline

Definition at line 341 of file undo_index.hpp.

341 {
342 auto p = alloc_traits::allocate(_allocator, 1);
343 auto guard0 = scope_exit{[&]{ alloc_traits::deallocate(_allocator, p, 1); }};
344 auto new_id = _next_id;
345 auto constructor = [&]( value_type& v ) {
346 v.id = new_id;
347 c( v );
348 };
349 alloc_traits::construct(_allocator, &*p, constructor, propagate_allocator(_allocator));
350 auto guard1 = scope_exit{[&]{ alloc_traits::destroy(_allocator, &*p); }};
351 if(!insert_impl<1>(p->_item))
352 BOOST_THROW_EXCEPTION( std::logic_error{ "could not insert object, most likely a uniqueness constraint was violated" } );
353 std::get<0>(_indices).push_back(p->_item); // cannot fail and we know that it will definitely insert at the end.
354 on_create(p->_item);
355 ++_next_id;
356 guard1.cancel();
357 guard0.cancel();
358 return p->_item;
359 }
auto & propagate_allocator(A< T > &a)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ empty()

template<typename T , typename Allocator , typename... Indices>
bool chainbase::undo_index< T, Allocator, Indices >::empty ( ) const
inline

Definition at line 563 of file undo_index.hpp.

563 {
564 return std::get<0>(_indices).empty();
565 }

◆ end()

template<typename T , typename Allocator , typename... Indices>
auto chainbase::undo_index< T, Allocator, Indices >::end ( ) const
inline

Definition at line 601 of file undo_index.hpp.

601{ return get<0>().end(); }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find()

template<typename T , typename Allocator , typename... Indices>
template<typename CompatibleKey >
const value_type * chainbase::undo_index< T, Allocator, Indices >::find ( CompatibleKey && key) const
inline

Definition at line 451 of file undo_index.hpp.

451 {
452 const auto& index = std::get<0>(_indices);
453 auto iter = index.find(static_cast<CompatibleKey&&>(key));
454 if (iter != index.end()) {
455 return &*iter;
456 } else {
457 return nullptr;
458 }
459 }
Here is the caller graph for this function:

◆ get() [1/3]

template<typename T , typename Allocator , typename... Indices>
template<typename Tag >
const auto & chainbase::undo_index< T, Allocator, Indices >::get ( ) const
inline

Definition at line 554 of file undo_index.hpp.

554{ return std::get<find_tag<Tag, Indices...>::value>(_indices); }
boost::mp11::mp_find< boost::mp11::mp_list< index_tag< Indices >... >, Tag > find_tag
#define value
Definition pkcs11.h:157
Here is the caller graph for this function:

◆ get() [2/3]

template<typename T , typename Allocator , typename... Indices>
template<int N>
const auto & chainbase::undo_index< T, Allocator, Indices >::get ( ) const
inline

Definition at line 557 of file undo_index.hpp.

557{ return std::get<N>(_indices); }

◆ get() [3/3]

template<typename T , typename Allocator , typename... Indices>
template<typename CompatibleKey >
const value_type & chainbase::undo_index< T, Allocator, Indices >::get ( CompatibleKey && key) const
inline

Definition at line 462 of file undo_index.hpp.

462 {
463 auto ptr = find( static_cast<CompatibleKey&&>(key) );
464 if( !ptr ) {
465 std::stringstream ss;
466 ss << "key not found (" << boost::core::demangle( typeid( key ).name() ) << "): " << key;
467 BOOST_THROW_EXCEPTION( std::out_of_range( ss.str().c_str() ) );
468 }
469 return *ptr;
470 }
std::string name
const value_type * find(CompatibleKey &&key) const
static const Segment ss(Segment::ss)
uint8_t key[16]
Definition yubico_otp.c:41
Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_undo_session()

template<typename T , typename Allocator , typename... Indices>
bool chainbase::undo_index< T, Allocator, Indices >::has_undo_session ( ) const
inline

Definition at line 579 of file undo_index.hpp.

579{ return !_undo_stack.empty(); }
Here is the caller graph for this function:

◆ indices()

template<typename T , typename Allocator , typename... Indices>
const undo_index & chainbase::undo_index< T, Allocator, Indices >::indices ( ) const
inline

Definition at line 552 of file undo_index.hpp.

552{ return *this; }

◆ last_undo_session()

template<typename T , typename Allocator , typename... Indices>
delta chainbase::undo_index< T, Allocator, Indices >::last_undo_session ( ) const
inline

Definition at line 587 of file undo_index.hpp.

587 {
588 if(_undo_stack.empty())
589 return { { get<0>().end(), get<0>().end() },
590 { _old_values.end(), _old_values.end() },
591 { _removed_values.end(), _removed_values.end() } };
592 // Warning: This is safe ONLY as long as nothing exposes the undo stack to client code.
593 // Compressing the undo stack does not change the logical state of the undo_index.
594 const_cast<undo_index*>(this)->compress_last_undo_session();
595 return { { get<0>().lower_bound(_undo_stack.back().old_next_id), get<0>().end() },
596 { _old_values.begin(), get_old_values_end(_undo_stack.back()) },
597 { _removed_values.begin(), get_removed_values_end(_undo_stack.back()) } };
598 }
void compress_last_undo_session() noexcept
Here is the call graph for this function:

◆ modify()

template<typename T , typename Allocator , typename... Indices>
template<typename Modifier >
void chainbase::undo_index< T, Allocator, Indices >::modify ( const value_type & obj,
Modifier && m )
inline

Definition at line 365 of file undo_index.hpp.

365 {
366 value_type* backup = on_modify(obj);
367 value_type& node_ref = const_cast<value_type&>(obj);
368 bool success = false;
369 {
370 auto guard0 = scope_exit{[&]{
371 if(!post_modify<true, 1>(node_ref)) { // The object id cannot be modified
372 if(backup) {
373 node_ref = std::move(*backup);
374 bool success = post_modify<true, 1>(node_ref);
375 (void)success;
376 assert(success);
377 assert(backup == &_old_values.front());
378 _old_values.pop_front_and_dispose([this](pointer p){ dispose_old(*p); });
379 } else {
380 remove(obj);
381 }
382 } else {
383 success = true;
384 }
385 }};
386 auto old_id = obj.id;
387 m(node_ref);
388 (void)old_id;
389 assert(obj.id == old_id);
390 }
391 if(!success)
392 BOOST_THROW_EXCEPTION( std::logic_error{ "could not modify object, most likely a uniqueness constraint was violated" } );
393 }
void remove(const value_type &obj) noexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ project() [1/2]

template<typename T , typename Allocator , typename... Indices>
template<typename Tag , typename Iter >
auto chainbase::undo_index< T, Allocator, Indices >::project ( Iter iter) const
inline

Definition at line 568 of file undo_index.hpp.

568 {
569 return project<find_tag<Tag, Indices...>::value>(iter);
570 }
auto project(Iter iter) const
Here is the call graph for this function:
Here is the caller graph for this function:

◆ project() [2/2]

template<typename T , typename Allocator , typename... Indices>
template<int N, typename Iter >
auto chainbase::undo_index< T, Allocator, Indices >::project ( Iter iter) const
inline

Definition at line 573 of file undo_index.hpp.

573 {
574 if(iter == get<boost::mp11::mp_find<boost::mp11::mp_list<typename set_impl<node, Indices>::const_iterator...>, Iter>::value>().end())
575 return get<N>().end();
576 return get<N>().iterator_to(*iter);
577 }
Here is the call graph for this function:

◆ remove()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::remove ( const value_type & obj)
inlinenoexcept

Definition at line 430 of file undo_index.hpp.

430 {
431 auto& node_ref = const_cast<value_type&>(obj);
432 erase_impl(node_ref);
433 if(on_remove(node_ref)) {
434 dispose_node(node_ref);
435 }
436 }
Here is the caller graph for this function:

◆ remove_object()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::remove_object ( int64_t id)
inline

Definition at line 472 of file undo_index.hpp.

472 {
473 const value_type* val = find( typename value_type::id_type(id) );
474 if( !val ) BOOST_THROW_EXCEPTION( std::out_of_range( boost::lexical_cast<std::string>(id) ) );
475 remove( *val );
476 }
Here is the call graph for this function:

◆ revision()

template<typename T , typename Allocator , typename... Indices>
int64_t chainbase::undo_index< T, Allocator, Indices >::revision ( ) const
inline

Definition at line 514 of file undo_index.hpp.

514{ return _revision; }
Here is the caller graph for this function:

◆ set_revision()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::set_revision ( uint64_t revision)
inline

Definition at line 520 of file undo_index.hpp.

520 {
521 if( _undo_stack.size() != 0 )
522 BOOST_THROW_EXCEPTION( std::logic_error("cannot set revision while there is an existing undo stack") );
523
524 if( revision > std::numeric_limits<int64_t>::max() )
525 BOOST_THROW_EXCEPTION( std::logic_error("revision to set is too high") );
526
527 if( static_cast<int64_t>(revision) < _revision )
528 BOOST_THROW_EXCEPTION( std::logic_error("revision cannot decrease") );
529
530 _revision = static_cast<int64_t>(revision);
531 }
signed __int64 int64_t
Definition stdint.h:135
Here is the call graph for this function:

◆ size()

template<typename T , typename Allocator , typename... Indices>
std::size_t chainbase::undo_index< T, Allocator, Indices >::size ( ) const
inline

Definition at line 559 of file undo_index.hpp.

559 {
560 return std::get<0>(_indices).size();
561 }

◆ squash()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::squash ( )
inlinenoexcept

Definition at line 655 of file undo_index.hpp.

655 {
657 }
void squash_and_compress() noexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ squash_and_compress()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::squash_and_compress ( )
inlinenoexcept

Definition at line 669 of file undo_index.hpp.

669 {
670 if(_undo_stack.size() >= 2) {
671 compress_impl(_undo_stack[_undo_stack.size() - 2]);
672 }
673 squash_fast();
674 }
void squash_fast() noexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ squash_fast()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::squash_fast ( )
inlinenoexcept

Definition at line 659 of file undo_index.hpp.

659 {
660 if (_undo_stack.empty()) {
661 return;
662 } else if (_undo_stack.size() == 1) {
663 dispose_undo();
664 }
665 _undo_stack.pop_back();
666 --_revision;
667 }
Here is the caller graph for this function:

◆ start_undo_session()

template<typename T , typename Allocator , typename... Indices>
session chainbase::undo_index< T, Allocator, Indices >::start_undo_session ( bool enabled)
inline

Definition at line 516 of file undo_index.hpp.

516 {
517 return session{*this, enabled};
518 }
CK_SESSION_HANDLE session
Here is the caller graph for this function:

◆ track_removed()

template<typename T , typename Allocator , typename... Indices>
auto chainbase::undo_index< T, Allocator, Indices >::track_removed ( )
inline

Definition at line 426 of file undo_index.hpp.

426 {
427 return removed_nodes_tracker(*this);
428 }
Here is the caller graph for this function:

◆ undo()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::undo ( )
inlinenoexcept

Definition at line 610 of file undo_index.hpp.

610 {
611 if (_undo_stack.empty()) return;
612 undo_state& undo_info = _undo_stack.back();
613 // erase all new_ids
614 auto& by_id = std::get<0>(_indices);
615 auto new_ids_iter = by_id.lower_bound(undo_info.old_next_id);
616 by_id.erase_and_dispose(new_ids_iter, by_id.end(), [this](pointer p){
617 erase_impl<1>(*p);
618 dispose_node(*p);
619 });
620 // replace old_values
621 _old_values.erase_after_and_dispose(_old_values.before_begin(), get_old_values_end(undo_info), [this, &undo_info](pointer p) {
622 auto restored_mtime = to_old_node(*p)._mtime;
623 // Skip restoring values that overwrite an earlier modify in the same session.
624 // Duplicate modifies can only happen because of squash.
625 if(restored_mtime < undo_info.ctime) {
626 auto iter = &to_old_node(*p)._current->_item;
627 *iter = std::move(*p);
628 auto& node_mtime = to_node(*iter)._mtime;
629 node_mtime = restored_mtime;
630 if (get_removed_field(*iter) != erased_flag) {
631 // Non-unique items are transient and are guaranteed to be fixed
632 // by the time we finish processing old_values.
633 post_modify<false, 1>(*iter);
634 } else {
635 // The item was removed. It will be inserted when we process removed_values
636 }
637 }
638 dispose_old(*p);
639 });
640 // insert all removed_values
641 _removed_values.erase_after_and_dispose(_removed_values.before_begin(), get_removed_values_end(undo_info), [this, &undo_info](pointer p) {
642 if (p->id < undo_info.old_next_id) {
643 get_removed_field(*p) = 0; // Will be overwritten by tree algorithms, because we're reusing the color.
644 insert_impl(*p);
645 } else {
646 dispose_node(*p);
647 }
648 });
649 _next_id = undo_info.old_next_id;
650 _undo_stack.pop_back();
651 --_revision;
652 }
static constexpr int erased_flag
alloc_traits::pointer _current
Here is the caller graph for this function:

◆ undo_all()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::undo_all ( )
inline

Definition at line 603 of file undo_index.hpp.

603 {
604 while(!_undo_stack.empty()) {
605 undo();
606 }
607 }
void undo() noexcept
Here is the call graph for this function:

◆ undo_stack_revision_range()

template<typename T , typename Allocator , typename... Indices>
std::pair< int64_t, int64_t > chainbase::undo_index< T, Allocator, Indices >::undo_stack_revision_range ( ) const
inline

Definition at line 533 of file undo_index.hpp.

533 {
534 return { _revision - _undo_stack.size(), _revision };
535 }

◆ validate()

template<typename T , typename Allocator , typename... Indices>
void chainbase::undo_index< T, Allocator, Indices >::validate ( ) const
inline

Definition at line 251 of file undo_index.hpp.

251 {
252 if( sizeof(node) != _size_of_value_type || sizeof(*this) != _size_of_this )
253 BOOST_THROW_EXCEPTION( std::runtime_error("content of memory does not match data expected by executable") );
254 }

Member Data Documentation

◆ erased_flag

template<typename T , typename Allocator , typename... Indices>
int chainbase::undo_index< T, Allocator, Indices >::erased_flag = 2
staticconstexpr

Definition at line 264 of file undo_index.hpp.


The documentation for this class was generated from the following file: