fixed skiplist and implemented the interface for skiplistset
This commit is contained in:
parent
904553b712
commit
126b95b454
@ -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<ConstIterator>
|
||||
{
|
||||
friend class SkipList;
|
||||
using IteratorBase<ConstIterator>::IteratorBase;
|
||||
ConstIterator(Node* node) : IteratorBase<ConstIterator>(node) {}
|
||||
|
||||
public:
|
||||
ConstIterator() = default;
|
||||
ConstIterator(const ConstIterator&) = default;
|
||||
|
||||
const value_type& operator*()
|
||||
{
|
||||
return IteratorBase<ConstIterator>::operator*();
|
||||
@ -296,7 +300,11 @@ public:
|
||||
class Iterator : public IteratorBase<Iterator>
|
||||
{
|
||||
friend class SkipList;
|
||||
using IteratorBase<Iterator>::IteratorBase;
|
||||
Iterator(Node* node) : IteratorBase<Iterator>(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<Iterator, bool> insert_unique(const K& key, const T& item)
|
||||
{
|
||||
return skiplist.insert({key, item}, preds, succs);
|
||||
return skiplist->insert({key, item}, preds, succs);
|
||||
}
|
||||
|
||||
std::pair<Iterator, bool> insert_unique(const K& key, T&& item)
|
||||
{
|
||||
return skiplist.insert({key, std::forward<T>(item)}, preds, succs);
|
||||
return skiplist->insert({key, std::forward<T>(item)}, preds, succs);
|
||||
}
|
||||
|
||||
ConstIterator find(const K& key) const
|
||||
{
|
||||
return skiplist.find(key);
|
||||
return static_cast<const SkipList&>(*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<ConstIterator>(key);
|
||||
return const_cast<SkipList*>(this)->find_node<ConstIterator>(key);
|
||||
}
|
||||
|
||||
Iterator find(const K& key)
|
||||
|
229
data_structures/skiplist/skiplistset.hpp
Normal file
229
data_structures/skiplist/skiplistset.hpp
Normal file
@ -0,0 +1,229 @@
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "skiplist.hpp"
|
||||
#include "utils/total_ordering.hpp"
|
||||
|
||||
template <class T, size_t H=32, class lock_t=SpinLock>
|
||||
class SkipListSet
|
||||
{
|
||||
class Key : public TotalOrdering<Key>
|
||||
{
|
||||
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<Key, T, H, lock_t>;
|
||||
using iter_t = typename skiplist_t::Iterator;
|
||||
using const_iter_t = typename skiplist_t::ConstIterator;
|
||||
|
||||
public:
|
||||
template <class Derived, class It>
|
||||
class IteratorBase : public Crtp<Derived>
|
||||
{
|
||||
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<ConstIterator, const_iter_t>
|
||||
{
|
||||
friend class SkipListSet;
|
||||
|
||||
using Base = IteratorBase<ConstIterator, const_iter_t>;
|
||||
|
||||
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<Iterator, iter_t>
|
||||
{
|
||||
friend class SkipListSet;
|
||||
|
||||
using Base = IteratorBase<Iterator, iter_t>;
|
||||
|
||||
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<Iterator, bool> 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<Key, T> data;
|
||||
};
|
54
examples/skiplistset.cpp
Normal file
54
examples/skiplistset.cpp
Normal file
@ -0,0 +1,54 @@
|
||||
#include <iostream>
|
||||
|
||||
#include "data_structures/skiplist/skiplistset.hpp"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
void print_skiplist(const SkipListSet<int>::Accessor& skiplist)
|
||||
{
|
||||
cout << "---- skiplist set now has: ";
|
||||
|
||||
for(auto& item : skiplist)
|
||||
cout << item << ", ";
|
||||
|
||||
cout << "----" << endl;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
SkipListSet<int> 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;
|
||||
}
|
@ -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<Null&>(*this));
|
||||
case Flags::True: return h.handle(static_cast<Bool&>(*this));
|
||||
case Flags::False: return h.handle(static_cast<Bool&>(*this));
|
||||
case Flags::String: return h.handle(static_cast<String&>(*this));
|
||||
|
@ -1,32 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "utils/auto_scope.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <execinfo.h>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -3,22 +3,22 @@
|
||||
template <class Derived>
|
||||
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);
|
||||
}
|
||||
|
@ -1,4 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "string/all.hpp"
|
||||
#include "sync/all.hpp"
|
Loading…
Reference in New Issue
Block a user