fixed skiplist and implemented the interface for skiplistset

This commit is contained in:
Dominik Tomičević 2015-12-14 09:30:32 +01:00
parent 904553b712
commit 126b95b454
7 changed files with 369 additions and 64 deletions

View File

@ -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)

View 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
View 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;
}

View File

@ -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));

View File

@ -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);
}

View File

@ -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);
}

View File

@ -1,4 +0,0 @@
#pragma once
#include "string/all.hpp"
#include "sync/all.hpp"