diff --git a/data_structures/skiplist/skiplist.hpp b/data_structures/skiplist/skiplist.hpp index 770d0602e..2446ab00f 100644 --- a/data_structures/skiplist/skiplist.hpp +++ b/data_structures/skiplist/skiplist.hpp @@ -110,7 +110,8 @@ public: */ struct Flags { - enum node_flags : uint8_t { + enum node_flags : uint8_t + { MARKED = 0x01, FULLY_LINKED = 0x10, }; @@ -274,9 +275,12 @@ public: class ConstIterator : public IteratorBase { friend class SkipList; - using IteratorBase::IteratorBase; + ConstIterator(Node* node) : IteratorBase(node) {} public: + ConstIterator() = default; + ConstIterator(const ConstIterator&) = default; + const value_type& operator*() { return IteratorBase::operator*(); @@ -296,7 +300,11 @@ public: class Iterator : public IteratorBase { friend class SkipList; - using IteratorBase::IteratorBase; + Iterator(Node* node) : IteratorBase(node) {} + + public: + Iterator() = default; + Iterator(const Iterator&) = default; }; SkipList() : header(Node::create(K(), std::move(T()), H)) {} @@ -307,74 +315,91 @@ public: { friend class SkipList; - Accessor(SkipList& skiplist) : skiplist(skiplist) {} + Accessor(SkipList* skiplist) : skiplist(skiplist) + { + assert(skiplist != nullptr); + // addref + } + public: Accessor(const Accessor&) = delete; - Accessor(Accessor&&) = default; + + Accessor(Accessor&& other) : skiplist(other.skiplist) + { + other.skiplist = nullptr; + } + + ~Accessor() + { + if(skiplist == nullptr) + return; + + // releaseref + } Iterator begin() { - return skiplist.begin(); + return skiplist->begin(); } ConstIterator begin() const { - return skiplist.cbegin(); + return skiplist->cbegin(); } ConstIterator cbegin() const { - return skiplist.cbegin(); + return skiplist->cbegin(); } Iterator end() { - return skiplist.end(); + return skiplist->end(); } ConstIterator end() const { - return skiplist.cend(); + return skiplist->cend(); } ConstIterator cend() const { - return skiplist.cend(); + return skiplist->cend(); } std::pair insert_unique(const K& key, const T& item) { - return skiplist.insert({key, item}, preds, succs); + return skiplist->insert({key, item}, preds, succs); } std::pair insert_unique(const K& key, T&& item) { - return skiplist.insert({key, std::forward(item)}, preds, succs); + return skiplist->insert({key, std::forward(item)}, preds, succs); } ConstIterator find(const K& key) const { - return skiplist.find(key); + return static_cast(*skiplist).find(key); } Iterator find(const K& key) { - return skiplist.find(key); + return skiplist->find(key); } bool remove(const K& key) { - return skiplist.remove(key, preds, succs); + return skiplist->remove(key, preds, succs); } private: - SkipList& skiplist; + SkipList* skiplist; Node* preds[H], *succs[H]; }; Accessor access() { - return Accessor(*this); + return Accessor(this); } private: @@ -427,7 +452,7 @@ private: ConstIterator find(const K& key) const { - return find_node(key); + return const_cast(this)->find_node(key); } Iterator find(const K& key) diff --git a/data_structures/skiplist/skiplistset.hpp b/data_structures/skiplist/skiplistset.hpp new file mode 100644 index 000000000..abf3f298d --- /dev/null +++ b/data_structures/skiplist/skiplistset.hpp @@ -0,0 +1,229 @@ +#pragma once + +#include + +#include "skiplist.hpp" +#include "utils/total_ordering.hpp" + +template +class SkipListSet +{ + class Key : public TotalOrdering + { + public: + Key() = default; + Key(const T* item) : item(item) {} + Key(const T& item) : item(&item) {} + + friend constexpr bool operator<(const Key& lhs, const Key& rhs) + { + assert(!lhs.empty()); + assert(!rhs.empty()); + + return *lhs.item < *rhs.item; + } + + friend constexpr bool operator==(const Key& lhs, const Key& rhs) + { + assert(!lhs.empty()); + assert(!rhs.empty()); + + return *lhs.item == *rhs.item; + } + + bool empty() const + { + return item == nullptr; + } + + operator const T&() const + { + assert(item != nullptr); + return *item; + } + + private: + const T* item {nullptr}; + }; + + using skiplist_t = SkipList; + using iter_t = typename skiplist_t::Iterator; + using const_iter_t = typename skiplist_t::ConstIterator; + +public: + template + class IteratorBase : public Crtp + { + protected: + IteratorBase(const It& it) : it(it) {} + IteratorBase(It&& it) : it(std::move(it)) {} + + It it; + public: + IteratorBase() = default; + IteratorBase(const IteratorBase&) = default; + + auto& operator*() + { + return it->second; + } + + auto* operator->() + { + return &it->second; + } + + operator T&() + { + return it->second; + } + + Derived& operator++() + { + it++; + return this->derived(); + } + + Derived& operator++(int) + { + return operator++(); + } + + friend bool operator==(const Derived& a, const Derived& b) + { + return a.it == b.it; + } + + friend bool operator!=(const Derived& a, const Derived& b) + { + return !(a == b); + } + }; + + class ConstIterator : public IteratorBase + { + friend class SkipListSet; + + using Base = IteratorBase; + + ConstIterator(const const_iter_t& it) : Base(it) {} + ConstIterator(const_iter_t&& it) : Base(std::move(it)) {} + + public: + ConstIterator() = default; + ConstIterator(const ConstIterator&) = default; + + const T& operator*() + { + return Base::operator*(); + } + + const T* operator->() + { + return Base::operator->(); + } + + operator const T&() + { + return Base::operator T&(); + } + }; + + class Iterator : public IteratorBase + { + friend class SkipListSet; + + using Base = IteratorBase; + + Iterator(const iter_t& it) : Base(it) {} + Iterator(iter_t&& it) : Base(std::move(it)) {} + + public: + Iterator() = default; + Iterator(const Iterator&) = default; + + }; + + SkipListSet() = default; + + friend class Accessor; + + class Accessor + { + friend class SkipListSet; + + using accessor_t = typename skiplist_t::Accessor; + Accessor(accessor_t&& accessor) : accessor(std::move(accessor)) {} + + public: + Accessor(const Accessor&) = delete; + Accessor(Accessor&&) = default; + + Iterator begin() + { + return Iterator(accessor.begin()); + } + + ConstIterator begin() const + { + return ConstIterator(accessor.cbegin()); + } + + ConstIterator cbegin() const + { + return ConstIterator(accessor.cbegin()); + } + + Iterator end() + { + return Iterator(accessor.end()); + } + + ConstIterator end() const + { + return ConstIterator(accessor.cend()); + } + + ConstIterator cend() const + { + return ConstIterator(accessor.cend()); + } + + std::pair insert(const T& item) + { + auto r = accessor.insert_unique(Key(item), item); + return { Iterator(r.first), r.second }; + } + + ConstIterator find(const T& item) const + { + return ConstIterator(accessor.find(Key(item))); + } + + Iterator find(const T& item) + { + return Iterator(accessor.find(Key(item))); + } + + bool contains(const T& item) const + { + return accessor.find(Key(item)) != accessor.end(); + } + + bool remove(const T& item) + { + return accessor.remove(Key(item)); + } + + private: + accessor_t accessor; + }; + + Accessor access() + { + return Accessor(std::move(data.access())); + } + +private: + SkipList data; +}; diff --git a/examples/skiplistset.cpp b/examples/skiplistset.cpp new file mode 100644 index 000000000..f85d17045 --- /dev/null +++ b/examples/skiplistset.cpp @@ -0,0 +1,54 @@ +#include + +#include "data_structures/skiplist/skiplistset.hpp" + +using std::cout; +using std::endl; + +void print_skiplist(const SkipListSet::Accessor& skiplist) +{ + cout << "---- skiplist set now has: "; + + for(auto& item : skiplist) + cout << item << ", "; + + cout << "----" << endl; +} + +int main(void) +{ + SkipListSet set; + auto accessor = set.access(); + + cout << std::boolalpha; + + cout << "added non-existing 1? (true) " + << accessor.insert(1).second << endl; + + cout << "added already existing 1? (false) " + << accessor.insert(1).second << endl; + + accessor.insert(2); + print_skiplist(accessor); + + cout << "item 3 doesn't exist? (true) " + << (accessor.find(3) == accessor.end()) << endl; + + cout << "item 3 exists? (false) " + << accessor.contains(3) << endl; + + cout << "item 2 exists? (true) " + << (accessor.find(2) != accessor.end()) << endl; + + cout << "at item 2 is? 2 " << *accessor.find(2) << endl; + + cout << "removed existing 1? (true) " << accessor.remove(1) << endl; + cout << "removed non-existing 3? (false) " << accessor.remove(3) << endl; + + accessor.insert(1); + accessor.insert(4); + + print_skiplist(accessor); + + return 0; +} diff --git a/storage/model/properties/property.hpp b/storage/model/properties/property.hpp index 72a8bb599..b0a6ce105 100644 --- a/storage/model/properties/property.hpp +++ b/storage/model/properties/property.hpp @@ -11,8 +11,6 @@ struct Property enum class Flags : unsigned { - Null = 0x1, - Bool = 0x2, True = 0x4 | Bool, False = 0x8 | Bool, @@ -58,18 +56,6 @@ struct Property Flags flags; }; -struct Null : public Property -{ - static constexpr Flags type = Flags::Null; - - Null() : Property(Flags::Null) {} - - bool is_null() - { - return true; - } -}; - struct Bool : public Property { static constexpr Flags type = Flags::Bool; @@ -89,7 +75,7 @@ struct String : public Property { static constexpr Flags type = Flags::String; - String(const std::string& value) + String(const std::string& value) : Property(Flags::String), value(value) {} String(std::string&& value) @@ -102,7 +88,7 @@ struct Int32 : public Property { static constexpr Flags type = Flags::Int32; - Int32(int32_t value) + Int32(int32_t value) : Property(Flags::Int32), value(value) {} int32_t value; @@ -112,7 +98,7 @@ struct Int64 : public Property { static constexpr Flags type = Flags::Int64; - Int64(int64_t value) + Int64(int64_t value) : Property(Flags::Int64), value(value) {} int64_t value; @@ -122,7 +108,7 @@ struct Float : public Property { static constexpr Flags type = Flags::Float; - Float(float value) + Float(float value) : Property(Flags::Float), value(value) {} float value; @@ -132,7 +118,7 @@ struct Double : public Property { static constexpr Flags type = Flags::Double; - Double(double value) + Double(double value) : Property(Flags::Double), value(value) {} double value; @@ -143,7 +129,6 @@ void Property::accept(Handler& h) { switch(flags) { - case Flags::Null: return h.handle(static_cast(*this)); case Flags::True: return h.handle(static_cast(*this)); case Flags::False: return h.handle(static_cast(*this)); case Flags::String: return h.handle(static_cast(*this)); diff --git a/utils/terminate_handler.hpp b/utils/terminate_handler.hpp index b022cf5a2..294d31151 100644 --- a/utils/terminate_handler.hpp +++ b/utils/terminate_handler.hpp @@ -1,32 +1,48 @@ #pragma once +#include "utils/auto_scope.hpp" + #include #include // TODO: log to local file or remote database -void stacktrace() noexcept +void stacktrace(std::ostream& stream) noexcept { - void *array[50]; - int size = backtrace(array, 50); - std::cout << __FUNCTION__ << " backtrace returned " << size << " frames\n\n"; - char **messages = backtrace_symbols(array, size); - for (int i = 0; i < size && messages != NULL; ++i) { - std::cout << "[bt]: (" << i << ") " << messages[i] << std::endl; - } - std::cout << std::endl; - free(messages); + void* array[50]; + int size = backtrace(array, 50); + + stream << __FUNCTION__ << " backtrace returned " + << size << " frames." << std::endl; + + char** messages = backtrace_symbols(array, size); + Auto(free(messages)); + + for (int i = 0; i < size && messages != NULL; ++i) + stream << "[bt]: (" << i << ") " << messages[i] << std::endl; + + stream << std::endl; } // TODO: log to local file or remote database -void terminate_handler() noexcept +void terminate_handler(std::ostream& stream) noexcept { - if (auto exc = std::current_exception()) { - try { + if(auto exc = std::current_exception()) + { + try + { std::rethrow_exception(exc); - } catch (std::exception &ex) { - std::cout << ex.what() << std::endl << std::endl; - stacktrace(); + } + catch(std::exception& ex) + { + stream << ex.what() << std::endl << std::endl; + stacktrace(stream); } } - std::_Exit(EXIT_FAILURE); + + std::abort(); +} + +void terminate_handler() noexcept +{ + terminate_handler(std::cout); } diff --git a/utils/total_ordering.hpp b/utils/total_ordering.hpp index 09651cf23..97f8871e3 100644 --- a/utils/total_ordering.hpp +++ b/utils/total_ordering.hpp @@ -3,22 +3,22 @@ template struct TotalOrdering { - friend bool operator!=(const Derived& a, const Derived& b) + friend constexpr bool operator!=(const Derived& a, const Derived& b) { return !(a == b); } - friend bool operator<=(const Derived& a, const Derived& b) + friend constexpr bool operator<=(const Derived& a, const Derived& b) { return a < b || a == b; } - friend bool operator>(const Derived& a, const Derived& b) + friend constexpr bool operator>(const Derived& a, const Derived& b) { return !(a <= b); } - friend bool operator>=(const Derived& a, const Derived& b) + friend constexpr bool operator>=(const Derived& a, const Derived& b) { return !(a < b); } diff --git a/utils/utils.hpp b/utils/utils.hpp deleted file mode 100644 index b59f1d3b0..000000000 --- a/utils/utils.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "string/all.hpp" -#include "sync/all.hpp"