8000 Replicated Logs Companion PR by maierlars · Pull Request #14484 · arangodb/arangodb · GitHub
[go: up one dir, main page]

Skip to content

Replicated Logs Companion PR #14484

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 40 commits into from
Jul 14, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
333d579
Began work on a value guarded by mutex implementation
goedderz Jul 9, 2019
4657757
Added (empty) test file
goedderz Jul 18, 2019
86ff2c1
A first test, and some fixes
goedderz Oct 9, 2019
08adbf4
Deleted copy&move constructors
goedderz Oct 10, 2019
ea01ee2
explicitly defaulted destructor
goedderz Oct 10, 2019
4326973
Switched to trailing return types
goedderz Oct 2, 2020
b8c7f3d
Some improvements and more tests
goedderz Nov 13, 2020
4c07156
Rename arangodb::Mutex::tryLock to make Mutex more compatible with st…
goedderz Nov 19, 2020
612aee7
Moved Guarded files to Basics
goedderz Nov 19, 2020
d691764
minor cleanup
goedderz Nov 19, 2020
1eec096
added comment
goedderz Nov 19, 2020
6ea04cc
parametrized lock
goedderz Nov 19, 2020
f01691e
added test assertions
goedderz Nov 20, 2020
a4e1735
Fixed windows, added a test
goedderz Nov 20, 2020
2d843dc
Added assign and copy
goedderz Nov 20, 2020
3971e76
Merge branch 'devel' of github.com:arangodb/arangodb into feature/gua…
goedderz Apr 16, 2021
09aa867
Add perfect forwarding in Guarded constructor
goedderz Apr 29, 2021
c206171
Merge branch 'devel' of github.com:arangodb/arangodb into feature/gua…
goedderz Jun 1, 2021
1561c4f
Backported some changes from replication-2.0
goedderz Jun 1, 2021
add04ec
Merge branch 'devel' of github.com:arangodb/arangodb into feature/gua…
goedderz Jun 29, 2021
c6668d3
Minor changes
goedderz Jun 29, 2021
ea89666
Added missing tests
goedderz Jun 29, 2021
731e8ad
Collected some changes from replication 2.0 PR.
Jul 8, 2021
18b6567
Added exception header.
Jul 8, 2021
f0f925b
More code that is not related to replicated logs.
Jul 8, 2021
b4ff84c
Merge remote-tracking branch 'origin/devel' into feature/replicated-l…
Jul 8, 2021
15f6f57
Added modifications on metrics feature api.
Jul 8, 2021
7ea920d
Added path components.
Jul 8, 2021
9b42045
Fixing clusterinfo.
Jul 8, 2021
db4c458
More reverts in logical collection.
Jul 8, 2021
09f0db3
Fixing Maintenance Tests.
Jul 8, 2021
52b76b3
Minor changes from review
goedderz Jul 9, 2021
d0ebb4c
Remove code duplication as suggested in the review
goedderz Jul 9, 2021
8e17cc0
Made FATAL_ERROR_(EXIT|ABORT) exception safe and replaced the macros …
goedderz Jul 12, 2021
7b75ac2
Merge branch 'feature/guarded-mutex' of https://github.com/arangodb/a…
goedderz Jul 12, 2021
bab222f
Merge branch 'devel' of https://github.com/arangodb/arangodb into fea…
goedderz Jul 12, 2021
8d27093
Added assertions to clarify a constructor's mode of operation
goedderz Jul 13, 2021
968854c
Changed and added an assertion to clarify the most important property
goedderz Jul 13, 2021
99e2b2f
Added some comments
goedderz Jul 13, 2021
638bf83
Fixed copyright header
goedderz Jul 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
< 8000 h5 data-view-component="true" class="mb-2"> Diff view
Diff view
Prev Previous commit
Next Next commit
Added assign and copy
  • Loading branch information
goedderz committed Nov 20, 2020
commit 2d843dcb0254aaa31978ec16c8d314bd7ffa087a
68 changes: 51 additions & 17 deletions lib/Basics/Guarded.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@
*
* getLockedGuard() will lock the mutex, and mutexGuard will release it upon
* destruction.
*
* For simple access, there are copy() and store():
*
* UnderGuard value = guarded.copy();
* guarded.store(UnderGuard{3});
*
* If copy/assign don't suffice for some reason - e.g. because you want to:
* - "try" for the lock, or
* - access to one specific member or anything like that, or
* - get/modify a non-copy-constructible or non-copy-assignable value,
* use any of the more general methods described above instead.
*/

namespace arangodb {
Expand Down Expand Up @@ -112,7 +123,7 @@ auto MutexGuard<T, L>::operator->() const noexcept -> T const* {
return std::addressof(get());
}

template <class T, class M = std::mutex, template<class> class L = std::unique_lock>
template <class T, class M = std::mutex, template <class> class L = std::unique_lock>
class Guarded {
public:
using value_type = T;
Expand Down Expand Up @@ -141,6 +152,14 @@ class Guarded {
class Q = std::conditional_t<std::is_void_v<R>, std::monostate, R>>
[[nodiscard]] auto tryUnderLock(F&& callback) const -> std::optional<Q>;

// get a copy of the value, made under the lock.
template <typename U = T, std::enable_if_t<std::is_copy_constructible_v<U>, int> = 0>
auto copy() const -> T;

// assign a new value using operator=, under the lock.
template <class U, std::enable_if_t<std::is_assignable_v<T, U>, int> = 0>
void assign(U&&);

auto getLockedGuard() -> MutexGuard<value_type, lock_type>;
auto getLockedGuard() const -> MutexGuard<value_type const, lock_type>;

Expand All @@ -150,20 +169,20 @@ class Guarded {

private:
value_type _value;
mutex_type _mutex;
mutable mutex_type _mutex;
};

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
Guarded<T, M, L>::Guarded(T&& value) : _value{std::move(value)}, _mutex{} {}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <typename... Args>
Guarded<T, M, L>::Guarded(Args... args) : _value{args...}, _mutex{} {}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <class F, class R>
auto Guarded<T, M, L>::doUnderLock(F&& callback) -> R {
auto guard = L<M>(_mutex);
auto guard = lock_type(_mutex);

if constexpr (!std::is_void_v<R>) {
return std::forward<F>(callback)(_value);
Expand All @@ -173,10 +192,10 @@ auto Guarded<T, M, L>::doUnderLock(F&& callback) -> R {
}
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <class F, class R>
auto Guarded<T, M, L>::doUnderLock(F&& callback) const -> R {
auto guard = L<M>(_mutex);
auto guard = lock_type(_mutex);

if constexpr (!std::is_void_v<R>) {
return std::forward<F>(callback)(_value);
Expand All @@ -186,10 +205,10 @@ auto Guarded<T, M, L>::doUnderLock(F&& callback) const -> R {
}
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <class F, class R, class Q>
auto Guarded<T, M, L>::tryUnderLock(F&& callback) -> std::optional<Q> {
auto guard = L<M>(_mutex, std::try_to_lock);
auto guard = lock_type(_mutex, std::try_to_lock);

if (guard.owns_lock()) {
if constexpr (!std::is_void_v<R>) {
Expand All @@ -203,7 +222,7 @@ auto Guarded<T, M, L>::tryUnderLock(F&& callback) -> std::optional<Q> {
}
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <class F, class R, class Q>
auto Guarded<T, M, L>::tryUnderLock(F&& callback) const -> std::optional<Q> {
auto guard = lock_type(_mutex, std::try_to_lock);
Expand All @@ -220,17 +239,31 @@ auto Guarded<T, M, L>::tryUnderLock(F&& callback) const -> std::optional<Q> {
}
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
template <typename U, std::enable_if_t<std::is_copy_constructible_v<U>, int>>
auto Guarded<T, M, L>::copy() const -> T {
auto guard = lock_type(this->_mutex);
return _value;
}

template <class T, class M, template <class> class L>
template <class U, std::enable_if_t<std::is_assignable_v<T, U>, int>>
void Guarded<T, M, L>::assign(U&& value) {
auto guard = lock_type(_mutex);
_value = std::forward<U>(value);
}

template <class T, class M, template <class> class L>
auto Guarded<T, M, L>::getLockedGuard() -> MutexGuard<T, L<M>> {
return MutexGuard(_value, lock_type{_mutex});
return MutexGuard(_value, lock_type(_mutex));
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
auto Guarded<T, M, L>::getLockedGuard() const -> MutexGuard<T const, L<M>> {
return MutexGuard(_value, lock_type(_mutex));
}

template <class T, class M, template<class> class L>
template <class T, class M, template <class> class L>
auto Guarded<T, M, L>::tryLockedGuard() -> std::optional<MutexGuard<T, L<M>>> {
auto lock = lock_type(_mutex, std::try_lock);

Expand All @@ -241,8 +274,9 @@ auto Guarded<T, M, L>::tryLockedGuard() -> std::optional<MutexGuard<T, L<M>>> {
}
}

template <class T, class M, template<class> class L>
auto Guarded<T, M, L>::tryLockedGuard() const -> std::optional<MutexGuard<T const, L<M>>> {
template <class T, class M, template <class> class L>
auto Guarded<T, M, L>::tryLockedGuard() const
-> std::optional<MutexGuard<T const, L<M>>> {
auto lock = lock_type(_mutex, std::try_lock);

if (lock.owns_lock()) {
Expand Down
65 changes: 49 additions & 16 deletions tests/Basics/GuardedTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,25 +41,56 @@ struct UnderGuardAtomic {
template <typename T>
class GuardedTest : public ::testing::Test {
protected:

using Mutex = typename T::first_type;
template<typename M>
template <typename M>
using Lock = typename T::second_type::template instantiate<M>;
template<typename V>
template <typename V>
using Guarded = Guarded<V, Mutex, Lock>;
};

TYPED_TEST_CASE_P(GuardedTest);

TYPED_TEST_P(GuardedTest, test_copy_allows_access) {
auto guardedObj = typename TestFixture::template Guarded<UnderGuard>{1};
auto const value = guardedObj.copy();
EXPECT_EQ(1, value.val);
EXPECT_EQ(1, guardedObj.copy().val);
}

TYPED_TEST_P(GuardedTest, test_copy_waits_for_access) {
// TODO Get a lock first, then assert that trying to copy waits for the lock
// to be released.
}

TYPED_TEST_P(GuardedTest, test_assign_allows_access) {
auto guardedObj = typename TestFixture::template Guarded<UnderGuard>{1};
EXPECT_EQ(1, guardedObj.copy().val);
// move assignment
guardedObj.assign(UnderGuard{2});
EXPECT_EQ(2, guardedObj.copy().val);
// copy assignment
auto const val = UnderGuard{3};
guardedObj.assign(val);
EXPECT_EQ(3, guardedObj.copy().val);
}

TYPED_TEST_P(GuardedTest, test_assign_waits_for_access) {
// TODO Get a lock first, then assert that trying to assign waits for the lock
// to be released.
}

TYPED_TEST_P(GuardedTest, test_guard_allows_access) {
auto guardedObj = typename TestFixture::template Guarded<UnderGuard>{1};
EXPECT_EQ(1, guardedObj.copy().val);
{
auto guard = guardedObj.getLockedGuard();
EXPECT_EQ(1, guard.get().val);
guard.get().val = 2;
EXPECT_EQ(2, guard.get().val);
}
EXPECT_EQ(2, guardedObj.copy().val);
}

TYPED_TEST_P(GuardedTest, test_guard_waits_for_access) {
auto guardedObj = typename TestFixture::template Guarded<UnderGuard>{1};
// TODO Get a lock first, then assert that trying to get a guard waits for the
Expand Down Expand Up @@ -96,13 +127,14 @@ TYPED_TEST_P(GuardedTest, test_do_waits_for_access) {
thr = std::thread([&] {
threadStarted.store(true, std::memory_order_release);
bool didExecute = false;
auto const res = guardedObj.doUnderLock([&didExecute](UnderGuardAtomic& obj) -> std::optional<std::monostate> {
EXPECT_EQ(1, obj.val.load(std::memory_order_relaxed));
obj.val.store(2, std::memory_order_release);
didExecute = true;
EXPECT_EQ(2, obj.val.load(std::memory_order_relaxed));
return std::monostate{};
});
auto const res = guardedObj.doUnderLock(
[&didExecute](UnderGuardAtomic& obj) -> std::optional<std::monostate> {
EXPECT_EQ(1, obj.val.load(std::memory_order_relaxed));
obj.val.store(2, std::memory_order_release);
didExecute = true;
EXPECT_EQ(2, obj.val.load(std::memory_order_relaxed));
return std::monostate{};
});
static_assert(std::is_same_v<std::optional<std::monostate> const, decltype(res)>);
EXPECT_TRUE(res.has_value());
EXPECT_TRUE(didExecute);
Expand Down Expand Up @@ -184,20 +216,21 @@ TYPED_TEST_P(GuardedTest, test_try_fails_access) {
}
}

REGISTER_TYPED_TEST_CASE_P(GuardedTest, test_guard_allows_access, test_guard_waits_for_access,
REGISTER_TYPED_TEST_CASE_P(GuardedTest, test_copy_allows_access, test_copy_waits_for_access,
test_assign_allows_access, test_assign_waits_for_access,
test_guard_allows_access, test_guard_waits_for_access,
test_do_allows_access, test_do_waits_for_access,
test_try_allows_access, test_try_fails_access);

template<template <typename> typename T>
template <template <typename> typename T>
struct ParamT {
template <typename U>
using instantiate = T<U>;
};

using TestedTypes = ::testing::Types<
std::pair<std::mutex, ParamT<std::unique_lock>>,
std::pair<arangodb::Mutex, ParamT<std::unique_lock>>
>;
using TestedTypes =
::testing::Types<std::pair<std::mutex, ParamT<std::unique_lock>>,
std::pair<arangodb::Mutex, ParamT<std::unique_lock>>>;

INSTANTIATE_TYPED_TEST_CASE_P(GuardedTestInstantiation, GuardedTest, TestedTypes);

Expand Down
0