diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2020-10-14 19:42:38 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2020-10-15 10:13:12 +0000 |
commit | b6a9d5894dc0d5ae8f896c4346a45fb20cf600b6 (patch) | |
tree | ad58d5aa3a4c7505124b91b7629875d98875a6bd /vespalib/src | |
parent | 36eb309ed6b9df96c4138fc57d3b002dd6dc6412 (diff) |
GC unused vespalib::MOnitor.
Diffstat (limited to 'vespalib/src')
-rw-r--r-- | vespalib/src/tests/sync/sync_test.cpp | 258 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/CMakeLists.txt | 1 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/overview.h | 11 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/sync.cpp | 99 | ||||
-rw-r--r-- | vespalib/src/vespa/vespalib/util/sync.h | 209 |
5 files changed, 38 insertions, 540 deletions
diff --git a/vespalib/src/tests/sync/sync_test.cpp b/vespalib/src/tests/sync/sync_test.cpp index 3a2cf0ea7a0..417a9779f9d 100644 --- a/vespalib/src/tests/sync/sync_test.cpp +++ b/vespalib/src/tests/sync/sync_test.cpp @@ -1,230 +1,48 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include <vespa/vespalib/testkit/testapp.h> -#include <vespa/vespalib/util/sync.h> +#include <vespa/vespalib/util/gate.h> -namespace vespalib { -class TryLock -{ -private: - friend class LockGuard; - friend class MonitorGuard; - - std::unique_lock<std::mutex> _guard; - std::condition_variable *_cond; - -public: - TryLock(const Monitor &mon) - : _guard(*mon._mutex, std::try_to_lock), - _cond(_guard ? mon._cond.get() : nullptr) - {} - ~TryLock() = default; - - TryLock(const TryLock &) = delete; - TryLock &operator=(const TryLock &) = delete; - - /** - * @brief Check whether this object holds a lock - * - * @return true if this object holds a lock - **/ - bool hasLock() const { return static_cast<bool>(_guard); } - void unlock() { - if (_guard) { - _guard.unlock(); - _cond = nullptr; - } - } -}; - -} using namespace vespalib; -#define CHECK_LOCKED(m) { TryLock tl(m); EXPECT_TRUE(!tl.hasLock()); } -#define CHECK_UNLOCKED(m) { TryLock tl(m); EXPECT_TRUE(tl.hasLock()); } - -class Test : public TestApp -{ -private: - Monitor _monitor; - - LockGuard lockMonitor() { return LockGuard(_monitor); } - MonitorGuard obtainMonitor() { return MonitorGuard(_monitor); } -public: - ~Test() override; - void testCountDownLatch(); - int Main() override; -}; - -Test::~Test() = default; - -void -Test::testCountDownLatch() { - { - CountDownLatch latch(5); - EXPECT_EQUAL(latch.getCount(), 5u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 4u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 3u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 2u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 1u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 0u); - latch.countDown(); - EXPECT_EQUAL(latch.getCount(), 0u); - latch.await(); // should not block - latch.await(); // should not block - } - { - Gate gate; - EXPECT_EQUAL(gate.getCount(), 1u); - gate.countDown(); - EXPECT_EQUAL(gate.getCount(), 0u); - gate.countDown(); - EXPECT_EQUAL(gate.getCount(), 0u); - gate.await(); // should not block - gate.await(); // should not block - } - { - Gate gate; - EXPECT_EQUAL(gate.getCount(), 1u); - EXPECT_EQUAL(gate.await(0), false); - EXPECT_EQUAL(gate.await(10), false); - gate.countDown(); - EXPECT_EQUAL(gate.getCount(), 0u); - EXPECT_EQUAL(gate.await(0), true); - EXPECT_EQUAL(gate.await(10), true); - } +TEST("testCountDownLatch") { + CountDownLatch latch(5); + EXPECT_EQUAL(latch.getCount(), 5u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 4u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 3u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 2u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 1u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 0u); + latch.countDown(); + EXPECT_EQUAL(latch.getCount(), 0u); + latch.await(); // should not block + latch.await(); // should not block +} +TEST("test gate dropping below zero") { + Gate gate; + EXPECT_EQUAL(gate.getCount(), 1u); + gate.countDown(); + EXPECT_EQUAL(gate.getCount(), 0u); + gate.countDown(); + EXPECT_EQUAL(gate.getCount(), 0u); + gate.await(); // should not block + gate.await(); // should not block } -int -Test::Main() -{ - TEST_INIT("sync_test"); - // you can use a LockGuard to lock a Monitor - { - Monitor monitor; - { - CHECK_UNLOCKED(monitor); - LockGuard guard(monitor); - CHECK_LOCKED(monitor); - } - CHECK_UNLOCKED(monitor); - { - LockGuard guard(monitor); - CHECK_LOCKED(monitor); - guard.unlock(); - CHECK_UNLOCKED(monitor); - } - } - { - Monitor monitor; - { - CHECK_UNLOCKED(monitor); - MonitorGuard guard(monitor); - guard.signal(); - guard.broadcast(); - guard.wait(10); - CHECK_LOCKED(monitor); - } - CHECK_UNLOCKED(monitor); - { - MonitorGuard guard(monitor); - CHECK_LOCKED(monitor); - guard.unlock(); - CHECK_UNLOCKED(monitor); - } - } - - // you can lock const objects - - { - const Monitor lock; - CHECK_UNLOCKED(lock); - LockGuard guard(lock); - CHECK_LOCKED(lock); - } - { - const Monitor monitor; - CHECK_UNLOCKED(monitor); - MonitorGuard guard(monitor); - CHECK_LOCKED(monitor); - } - // LockGuard/MonitorGuard have destructive move - { - Monitor lock; - CHECK_UNLOCKED(lock); - LockGuard a(lock); - CHECK_LOCKED(lock); - { - CHECK_LOCKED(lock); - LockGuard b(std::move(a)); - CHECK_LOCKED(lock); - } - CHECK_UNLOCKED(lock); - } - { - Monitor mon; - CHECK_UNLOCKED(mon); - MonitorGuard a(mon); - CHECK_LOCKED(mon); - { - CHECK_LOCKED(mon); - MonitorGuard b(std::move(a)); - CHECK_LOCKED(mon); - } - CHECK_UNLOCKED(mon); - } - // Destructive copy also works for return value handover - { - CHECK_UNLOCKED(_monitor); - { - CHECK_UNLOCKED(_monitor); - CHECK_UNLOCKED(_monitor); - LockGuard b = lockMonitor(); // copy, not assign - CHECK_LOCKED(_monitor); - } - CHECK_UNLOCKED(_monitor); - } - { - CHECK_UNLOCKED(_monitor); - { - CHECK_UNLOCKED(_monitor); - MonitorGuard guard(obtainMonitor()); - CHECK_LOCKED(_monitor); - } - CHECK_UNLOCKED(_monitor); - } - // Test that guards can be matched to locks/monitors - { - Monitor lock1; - Monitor lock2; - LockGuard lockGuard1(lock1); - LockGuard lockGuard2(lock2); - EXPECT_TRUE(lockGuard1.locks(lock1)); - EXPECT_FALSE(lockGuard1.locks(lock2)); - EXPECT_TRUE(lockGuard2.locks(lock2)); - EXPECT_FALSE(lockGuard2.locks(lock1)); - lockGuard1.unlock(); - EXPECT_FALSE(lockGuard1.locks(lock1)); - } - { - Monitor lock1; - Monitor lock2; - MonitorGuard lockGuard1(lock1); - MonitorGuard lockGuard2(lock2); - EXPECT_TRUE(lockGuard1.monitors(lock1)); - EXPECT_FALSE(lockGuard1.monitors(lock2)); - EXPECT_TRUE(lockGuard2.monitors(lock2)); - EXPECT_FALSE(lockGuard2.monitors(lock1)); - lockGuard1.unlock(); - EXPECT_FALSE(lockGuard1.monitors(lock1)); - } - testCountDownLatch(); - TEST_DONE(); +TEST("test gate non blocking await return correct states") { + Gate gate; + EXPECT_EQUAL(gate.getCount(), 1u); + EXPECT_EQUAL(gate.await(0), false); + EXPECT_EQUAL(gate.await(10), false); + gate.countDown(); + EXPECT_EQUAL(gate.getCount(), 0u); + EXPECT_EQUAL(gate.await(0), true); + EXPECT_EQUAL(gate.await(10), true); } -TEST_APPHOOK(Test) +TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/vespa/vespalib/util/CMakeLists.txt b/vespalib/src/vespa/vespalib/util/CMakeLists.txt index ea2189fc3a8..610310fd43c 100644 --- a/vespalib/src/vespa/vespalib/util/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/util/CMakeLists.txt @@ -49,7 +49,6 @@ vespa_add_library(vespalib_vespalib_util OBJECT stash.cpp string_hash.cpp stringfmt.cpp - sync.cpp thread.cpp thread_bundle.cpp threadstackexecutor.cpp diff --git a/vespalib/src/vespa/vespalib/util/overview.h b/vespalib/src/vespa/vespalib/util/overview.h index 7849887a14c..311071b4429 100644 --- a/vespalib/src/vespa/vespalib/util/overview.h +++ b/vespalib/src/vespa/vespalib/util/overview.h @@ -22,17 +22,6 @@ * * vespalib::GenCnt * - * Synchronization classes - * - * vespalib::Lock - * <BR> vespalib::LockGuard - * <BR> vespalib::Monitor - * <BR> vespalib::TryLock - * <BR> vespalib::MonitorGuard - * <BR> vespalib::RWLock - * <BR> vespalib::RWLockReader - * <BR> vespalib::RWLockWriter - * * Reference counting * * <BR> vespalib::ReferenceCounter diff --git a/vespalib/src/vespa/vespalib/util/sync.cpp b/vespalib/src/vespa/vespalib/util/sync.cpp deleted file mode 100644 index 1f7a5215c46..00000000000 --- a/vespalib/src/vespa/vespalib/util/sync.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "sync.h" -#include <cassert> - -namespace vespalib { - -Monitor::Monitor() noexcept - : _mutex(std::make_unique<std::mutex>()), - _cond(std::make_unique<std::condition_variable>()) -{} -Monitor::Monitor(Monitor &&rhs) noexcept = default; -Monitor::~Monitor() = default; - -LockGuard::LockGuard() : _guard() {} - -LockGuard::LockGuard(LockGuard &&rhs) noexcept : _guard(std::move(rhs._guard)) { } -LockGuard::LockGuard(const Monitor &lock) : _guard(*lock._mutex) { } - -LockGuard & -LockGuard::operator=(LockGuard &&rhs) noexcept{ - if (this != &rhs) { - _guard = std::move(rhs._guard); - } - return *this; -} - -void -LockGuard::unlock() { - if (_guard) { - _guard.unlock(); - } -} -LockGuard::~LockGuard() = default; - -bool -LockGuard::locks(const Monitor & lock) const { - return (_guard && _guard.mutex() == lock._mutex.get()); -} - -MonitorGuard::MonitorGuard() : _guard(), _cond(nullptr) {} -MonitorGuard::MonitorGuard(MonitorGuard &&rhs) noexcept - : _guard(std::move(rhs._guard)), - _cond(rhs._cond) -{ - rhs._cond = nullptr; -} -MonitorGuard::MonitorGuard(const Monitor &monitor) - : _guard(*monitor._mutex), - _cond(monitor._cond.get()) -{ } - -MonitorGuard & -MonitorGuard::operator=(MonitorGuard &&rhs) noexcept { - if (this != &rhs) { - _guard = std::move(rhs._guard); - _cond = rhs._cond; - rhs._cond = nullptr; - } - return *this; -} - -void -MonitorGuard::unlock() { - assert(_guard); - _guard.unlock(); - _cond = nullptr; -} -void -MonitorGuard::wait() { - _cond->wait(_guard); -} -bool -MonitorGuard::wait(int msTimeout) { - return wait(std::chrono::milliseconds(msTimeout)); -} -bool -MonitorGuard::wait(std::chrono::nanoseconds timeout) { - return _cond->wait_for(_guard, timeout) == std::cv_status::no_timeout; -} -void -MonitorGuard::signal() { - _cond->notify_one(); -} -void -MonitorGuard::broadcast() { - _cond->notify_all(); -} -void -MonitorGuard::unsafeSignalUnlock() { - _guard.unlock(); - _cond->notify_one(); - _cond = nullptr; -} - -MonitorGuard::~MonitorGuard() = default; - -} // namespace vespalib - diff --git a/vespalib/src/vespa/vespalib/util/sync.h b/vespalib/src/vespa/vespalib/util/sync.h deleted file mode 100644 index d66a53cf539..00000000000 --- a/vespalib/src/vespa/vespalib/util/sync.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#pragma once - -#include "time.h" -#include <mutex> -#include <condition_variable> - -namespace vespalib { - -/** - * @brief A Monitor is a synchronization primitive used to protect - * data access and also facilitate signaling and waiting between - * threads. - * - * A LockGuard can be used to obtain a lock on a Monitor. If you also - * want to send or wait for signals, you need to use a MonitorGuard. - * - * It is possible to obtain a lock on a const Monitor object. - * - * @see TryLock - **/ -class Monitor -{ -private: - friend class LockGuard; - friend class MonitorGuard; - friend class TryLock; - - std::unique_ptr<std::mutex> _mutex; - std::unique_ptr<std::condition_variable> _cond; -public: - /** - * @brief Create a new Monitor. - * - * Creates a Monitor that has mutex instrumentation disabled. - **/ - Monitor() noexcept; - Monitor(Monitor && rhs) noexcept; - ~Monitor(); -}; - - -/** - * @brief A LockGuard holds the lock on either a Lock or a Monitor. - * - * LockGuards are typically created on the stack to hold a lock within - * a scope. If needed, the unlock method may be used to release the - * lock before exiting scope. - * - * LockGuard has destructive copy. Copying a LockGuard has the - * semantic of transferring the lock from one object to the - * other. Note that assignment is not legal, and that copying a - * LockGuard that does not have a lock will result in an assert. - **/ -class LockGuard -{ -private: - std::unique_lock<std::mutex> _guard; -public: - /** - * @brief A noop guard without any mutex. - **/ - LockGuard(); - LockGuard(const LockGuard &rhs) = delete; - LockGuard &operator=(const LockGuard &) = delete; - - /** - * @brief Steal the lock from the given LockGuard - * - * @param rhs steal the lock from this one - **/ - LockGuard(LockGuard &&rhs) noexcept; - /** - * @brief Obtain the lock represented by the given Lock object. - * - * The method will block until the lock can be obtained. - * - * @param lock take it - **/ - LockGuard(const Monitor &lock); - - LockGuard &operator=(LockGuard &&rhs) noexcept; - - /** - * @brief Release the lock held by this object. - * - * No methods may be invoked after invoking unlock (except the - * destructor). Note that this method should only be used if you - * need to release the lock before the object is destructed, as - * the destructor will release the lock. - **/ - void unlock(); - /** - * @brief Release the lock held by this object if unlock has not - * been called. - **/ - ~LockGuard(); - - /** - * Allow code to match guard with lock. This allows functions to take a - * guard ref as input, ensuring that the caller have grabbed a lock. - */ - bool locks(const Monitor& lock) const; -}; - - -/** - * @brief A MonitorGuard holds the lock on a Monitor and supports - * sending and waiting for signals. - * - * MonitorGuards are typically created on the stack to hold a lock - * within a scope. If needed, the unlock method may be used to release - * the lock before exiting scope. - * - * MonitorGuard has destructive copy. Copying a MonitorGuard has the - * semantic of transferring the lock from one object to the - * other. Note that assignment is not legal, and that copying a - * MonitorGuard that does not have a lock will result in an assert. - **/ -class MonitorGuard -{ -private: - std::unique_lock<std::mutex> _guard; - std::condition_variable *_cond; - MonitorGuard &operator=(const MonitorGuard &) = delete; - -public: - /** - * @brief A noop guard without any condition. - **/ - MonitorGuard(); - MonitorGuard(const MonitorGuard &rhs) = delete; - /** - * @brief Steal the lock from the given MonitorGuard - * - * @param rhs steal the lock from this one - **/ - MonitorGuard(MonitorGuard &&rhs) noexcept; - /** - * @brief Obtain the lock on the given Monitor object. - * - * The method will block until the lock can be obtained. - * - * @param monitor take the lock on it - **/ - MonitorGuard(const Monitor &monitor); - - MonitorGuard &operator=(MonitorGuard &&rhs) noexcept; - - - /** - * @brief Release the lock held by this object. - * - * No methods may be invoked after invoking this one (except the - * destructor). Note that this method should only be used if you - * need to release the lock before this object is destructed, as - * the destructor will release the lock. - **/ - void unlock(); - /** - * @brief Wait for a signal on the underlying Monitor. - **/ - void wait(); - /** - * @brief Wait for a signal on the underlying Monitor with the - * given timeout. - * - * @param msTimeout timeout in milliseconds - * @return true if a signal was received, false if the wait timed out. - **/ - bool wait(int msTimeout); - bool wait(duration timeout); - /** - * @brief Send a signal to a single waiter on the underlying - * Monitor. - **/ - void signal(); - /** - * @brief Send a signal to all waiters on the underlying Monitor. - **/ - void broadcast(); - /** - * @brief Send a signal to a single waiter on the underlying - * Monitor, but unlock the monitor right before doing so. - * - * This is inherently unsafe and the caller needs external - * synchronization to ensure that the underlying Monitor object - * will live long enough to be signaled. - **/ - void unsafeSignalUnlock(); - - /** - * @brief Release the lock held by this object if unlock has not - * been called. - **/ - ~MonitorGuard(); - - /** - * Allow code to match guard with lock. This allows functions to take a - * guard ref as input, ensuring that the caller have grabbed a lock. - */ - bool monitors(const Monitor& m) const { - return (_cond != nullptr && _cond == m._cond.get()); - } -}; - -} // namespace vespalib - |