diff --git a/src/data_structures/concurrent/common.hpp b/src/data_structures/concurrent/common.hpp index feec09a33..6ff745a75 100644 --- a/src/data_structures/concurrent/common.hpp +++ b/src/data_structures/concurrent/common.hpp @@ -42,9 +42,11 @@ class Item : public TotalOrdering>, // Common base for accessor of all derived containers(ConcurrentMap, // ConcurrentSet, ...) from SkipList. -template +template class AccessorBase { - typedef SkipList list; + typedef + typename std::conditional, SkipList>::type + list; typedef typename SkipList::Iterator list_it; typedef typename SkipList::ConstIterator list_it_con; @@ -60,20 +62,20 @@ class AccessorBase { size_t size() { return accessor.size(); }; - list_it begin() { return accessor.begin(); } + auto begin() { return accessor.begin(); } - list_it_con begin() const { return accessor.cbegin(); } + auto begin() const { return accessor.cbegin(); } list_it_con cbegin() const { return accessor.cbegin(); } - list_it end() { return accessor.end(); } + auto end() { return accessor.end(); } - list_it_con end() const { return accessor.cend(); } + auto end() const { return accessor.cend(); } list_it_con cend() const { return accessor.cend(); } size_t size() const { return accessor.size(); } protected: - typename list::template Accessor> accessor; + decltype(std::declval().access()) accessor; }; diff --git a/src/data_structures/concurrent/concurrent_map.hpp b/src/data_structures/concurrent/concurrent_map.hpp index 1c9a0e579..c33404e6b 100644 --- a/src/data_structures/concurrent/concurrent_map.hpp +++ b/src/data_structures/concurrent/concurrent_map.hpp @@ -21,13 +21,14 @@ class ConcurrentMap { public: ConcurrentMap() {} - class Accessor : public AccessorBase { + template + class Accessor : public AccessorBase { friend class ConcurrentMap; - using AccessorBase::AccessorBase; + using AccessorBase::AccessorBase; private: - using AccessorBase::accessor; + using AccessorBase::accessor; public: std::pair insert(const K &key, const T &data) { @@ -71,10 +72,8 @@ class ConcurrentMap { bool remove(const K &key) { return accessor.remove(key); } }; - Accessor access() { return Accessor(&skiplist); } - - // TODO: - // const Accessor access() const { return Accessor(&skiplist); } + auto access() { return Accessor(&skiplist); } + auto access() const { return Accessor(&skiplist); } private: list skiplist; diff --git a/src/data_structures/concurrent/concurrent_set.hpp b/src/data_structures/concurrent/concurrent_set.hpp index 906803af0..0142cb0ab 100644 --- a/src/data_structures/concurrent/concurrent_set.hpp +++ b/src/data_structures/concurrent/concurrent_set.hpp @@ -14,13 +14,14 @@ class ConcurrentSet { public: ConcurrentSet() {} - class Accessor : public AccessorBase { + template + class Accessor : public AccessorBase { friend class ConcurrentSet; - using AccessorBase::AccessorBase; + using AccessorBase::AccessorBase; private: - using AccessorBase::accessor; + using AccessorBase::accessor; public: std::pair insert(const T &item) { @@ -60,9 +61,8 @@ class ConcurrentSet { bool remove(const T &item) { return accessor.remove(item); } }; - Accessor access() { return Accessor(&skiplist); } - - const Accessor access() const { return Accessor(&skiplist); } + auto access() { return Accessor(&skiplist); } + auto access() const { return Accessor(&skiplist); } private: list skiplist; diff --git a/src/data_structures/concurrent/skiplist.hpp b/src/data_structures/concurrent/skiplist.hpp index 8c686f652..5c65a4c0c 100644 --- a/src/data_structures/concurrent/skiplist.hpp +++ b/src/data_structures/concurrent/skiplist.hpp @@ -475,37 +475,11 @@ class SkipList : private Lockable { status_.alive_ = false; } - // TODO(dgleich): Remove after C++17 compile flag. - template - struct negation : std::integral_constant {}; - - template - Iterator begin(typename std::enable_if< - negation>::value>::type * = 0) { - return skiplist->begin(); - } - - template - ConstIterator begin( - typename std::enable_if::value>::type * = - 0) const { - return skiplist->cbegin(); - } + auto begin() const { return skiplist->begin(); } ConstIterator cbegin() const { return skiplist->cbegin(); } - template - Iterator end(typename std::enable_if< - negation>::value>::type * = 0) { - return skiplist->end(); - } - - template - ConstIterator end( - typename std::enable_if::value>::type * = - 0) const { - return skiplist->cend(); - } + auto end() const { return skiplist->end(); } ConstIterator cend() const { return skiplist->cend(); } @@ -700,7 +674,7 @@ class SkipList : private Lockable { Accessor access() { return Accessor(this); } - Accessor caccess() const { + Accessor access() const { return Accessor(this); } diff --git a/src/storage/locking/record_lock.cpp b/src/storage/locking/record_lock.cpp index 434a3575a..2826d6512 100644 --- a/src/storage/locking/record_lock.cpp +++ b/src/storage/locking/record_lock.cpp @@ -18,7 +18,7 @@ namespace { // returned. std::experimental::optional FindOldestTxInLockCycle( tx::transaction_id_t start, - ConcurrentMap::Accessor + ConcurrentMap::Accessor<> &graph_accessor) { std::vector path; std::unordered_set visited; diff --git a/tests/concurrent/common.hpp b/tests/concurrent/common.hpp index ce3fc930f..cbac599b7 100644 --- a/tests/concurrent/common.hpp +++ b/tests/concurrent/common.hpp @@ -40,7 +40,7 @@ auto rand_gen_bool(size_t n = 1) { // Checks for all owned keys if there data is data. template -void check_present_same(typename S::Accessor &acc, size_t data, +void check_present_same(typename S::template Accessor<> &acc, size_t data, std::vector &owned) { for (auto num : owned) { CHECK(acc.find(num)->second == data) << "My data is present and my"; @@ -49,7 +49,7 @@ void check_present_same(typename S::Accessor &acc, size_t data, // Checks for all owned.second keys if there data is owned.first. template -void check_present_same(typename S::Accessor &acc, +void check_present_same(typename S::template Accessor<> &acc, std::pair> &owned) { check_present_same(acc, owned.first, owned.second); } @@ -74,7 +74,7 @@ void check_size_list(S &acc, long long size) { << iterator_counter; } template -void check_size(typename S::Accessor &acc, long long size) { +void check_size(typename S::template Accessor<> &acc, long long size) { // check size CHECK(acc.size() == size) @@ -94,7 +94,7 @@ void check_size(typename S::Accessor &acc, long long size) { // Checks if order in list is maintened. It expects map template -void check_order(typename S::Accessor &acc) { +void check_order(typename S::template Accessor<> &acc) { if (acc.begin() != acc.end()) { auto last = acc.begin()->first; for (auto elem : acc) { @@ -122,10 +122,9 @@ void check_set(DynamicBitset<> &db, std::vector &set) { // Runs given function in threads_no threads and returns vector of futures for // there // results. -template -std::vector>> run( - size_t threads_no, S &skiplist, - std::function f) { +template +std::vector>> run(size_t threads_no, + S &skiplist, FunT f) { std::vector>> futures; for (size_t thread_i = 0; thread_i < threads_no; ++thread_i) { @@ -181,7 +180,7 @@ std::vector collect_set( // Returns object which tracs in owned which (key,data) where added and // downcounts. template -auto insert_try(typename S::Accessor &acc, long long &downcount, +auto insert_try(typename S::template Accessor<> &acc, long long &downcount, std::vector &owned) { return [&](K key, D data) mutable { if (acc.insert(key, data).second) { diff --git a/tests/concurrent/sl_set.cpp b/tests/concurrent/sl_set.cpp index 388082942..1b0cbc48f 100644 --- a/tests/concurrent/sl_set.cpp +++ b/tests/concurrent/sl_set.cpp @@ -16,6 +16,7 @@ int main(int argc, char **argv) { auto futures = run>(THREADS_NO, skiplist, [](auto acc, auto index) { + auto rand = rand_gen(key_range); auto rand_op = rand_gen_bool(no_insert_for_one_delete); long long downcount = op_per_thread; diff --git a/tests/unit/concurrent_map.cpp b/tests/unit/concurrent_map.cpp index d1bf491fd..5bd9b4f6c 100644 --- a/tests/unit/concurrent_map.cpp +++ b/tests/unit/concurrent_map.cpp @@ -8,7 +8,7 @@ using concurrent_map_t = ConcurrentMap; -void print_skiplist(const concurrent_map_t::Accessor &map) { +void print_skiplist(const concurrent_map_t::Accessor &map) { DLOG(INFO) << "Map now has: "; for (auto &kv : map) DLOG(INFO) << fmt::format(" ({}, {})", kv.first, kv.second); diff --git a/tests/unit/concurrent_map_access.cpp b/tests/unit/concurrent_map_access.cpp new file mode 100644 index 000000000..45d218cab --- /dev/null +++ b/tests/unit/concurrent_map_access.cpp @@ -0,0 +1,47 @@ +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include + +#include "data_structures/concurrent/concurrent_map.hpp" + +TEST(ConcurrentMap, Access) { + ConcurrentMap input; + { + auto accessor = input.access(); + accessor.insert(1, 1); + accessor.insert(2, 2); + accessor.insert(3, 3); + } + + auto accessor = input.access(); + std::vector results; + for (auto it = accessor.begin(); it != accessor.end(); ++it) + results.push_back(it->first); + + EXPECT_THAT(results, testing::ElementsAre(1, 2, 3)); +} + +TEST(ConcurrentMap, ConstAccess) { + ConcurrentMap input; + { + auto accessor = input.access(); + accessor.insert(1, 1); + accessor.insert(2, 2); + accessor.insert(3, 3); + } + + const ConcurrentMap &map = input; + auto accessor = map.access(); + + std::vector results; + for (auto it = accessor.begin(); it != accessor.end(); ++it) + results.push_back(it->first); + + EXPECT_THAT(results, testing::ElementsAre(1, 2, 3)); +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/unit/concurrent_set.cpp b/tests/unit/concurrent_set.cpp index c894f60b1..12275c65e 100644 --- a/tests/unit/concurrent_set.cpp +++ b/tests/unit/concurrent_set.cpp @@ -6,7 +6,7 @@ #include "data_structures/concurrent/concurrent_set.hpp" #include "utils/assert.hpp" -void print_skiplist(const ConcurrentSet::Accessor &skiplist) { +void print_skiplist(const ConcurrentSet::Accessor &skiplist) { DLOG(INFO) << "Skiplist set now has:"; for (auto &item : skiplist) DLOG(INFO) << item; } diff --git a/tests/unit/skiplist_access.cpp b/tests/unit/skiplist_access.cpp index 3482b8e0f..6f9b24309 100644 --- a/tests/unit/skiplist_access.cpp +++ b/tests/unit/skiplist_access.cpp @@ -32,7 +32,7 @@ TEST(SkipList, ConstAccess) { } const SkipList &skiplist = input; - auto accessor = skiplist.caccess(); + auto accessor = skiplist.access(); std::vector results; for (auto it = accessor.begin(); it != accessor.end(); ++it)