diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2020-10-07 20:29:40 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2020-10-07 20:53:05 +0000 |
commit | 356172042cbc96375be8d663a945879b9f10dd41 (patch) | |
tree | e77fb1af93766b3655df04a55a9fa5dee6ef7971 /vespalib | |
parent | 379b3d8c3ce128da5a985ed73fce99326369512c (diff) |
- GC unused code.
- vespalib::Lock -> std::mutex
Diffstat (limited to 'vespalib')
24 files changed, 87 insertions, 1830 deletions
diff --git a/vespalib/CMakeLists.txt b/vespalib/CMakeLists.txt index ec003329999..278d32c118d 100644 --- a/vespalib/CMakeLists.txt +++ b/vespalib/CMakeLists.txt @@ -46,7 +46,6 @@ vespa_define_module( src/tests/datastore/unique_store src/tests/datastore/unique_store_dictionary src/tests/datastore/unique_store_string_allocator - src/tests/delegatelist src/tests/detect_type_benchmark src/tests/dotproduct src/tests/drop-file-from-cache @@ -94,7 +93,6 @@ vespa_define_module( src/tests/regex src/tests/rendezvous src/tests/runnable_pair - src/tests/rwlock src/tests/sha1 src/tests/sharedptr src/tests/signalhandler diff --git a/vespalib/src/tests/delegatelist/.cvsignore b/vespalib/src/tests/delegatelist/.cvsignore deleted file mode 100644 index 0e8f4d0be0b..00000000000 --- a/vespalib/src/tests/delegatelist/.cvsignore +++ /dev/null @@ -1,3 +0,0 @@ -.depend -Makefile -delegatelist_test diff --git a/vespalib/src/tests/delegatelist/.gitignore b/vespalib/src/tests/delegatelist/.gitignore deleted file mode 100644 index 42ac4beb0c3..00000000000 --- a/vespalib/src/tests/delegatelist/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.depend -Makefile -delegatelist_test -vespalib_delegatelist_test_app diff --git a/vespalib/src/tests/delegatelist/CMakeLists.txt b/vespalib/src/tests/delegatelist/CMakeLists.txt deleted file mode 100644 index 71551474445..00000000000 --- a/vespalib/src/tests/delegatelist/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(vespalib_delegatelist_test_app TEST - SOURCES - delegatelist.cpp - DEPENDS - vespalib -) -vespa_add_test(NAME vespalib_delegatelist_test_app COMMAND vespalib_delegatelist_test_app) diff --git a/vespalib/src/tests/delegatelist/delegatelist.cpp b/vespalib/src/tests/delegatelist/delegatelist.cpp deleted file mode 100644 index 4dc7e5c97d7..00000000000 --- a/vespalib/src/tests/delegatelist/delegatelist.cpp +++ /dev/null @@ -1,824 +0,0 @@ -// 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/delegatelist.hpp> -#include <vespa/vespalib/util/guard.h> -#include <vespa/fastos/thread.h> -#include <queue> - -#include <vespa/log/log.h> -LOG_SETUP("delegatelist_test"); - -using namespace vespalib; - -//----------------------------------------------------------------------------- - -class Test : public TestApp -{ -public: - void testEmpty(); - void testAdd(); - void testRemove(); - void testOneShot(); - void testMultiSnapshot(); - void testActors(); - void testWaitSnapshots(); - void stressTest(); - int Main() override; -}; - -//----------------------------------------------------------------------------- - -namespace { - -class Handler -{ -private: - int _num; -public: - Handler() : _num(0) {} - void add() { _num++; } - int getNum() { return _num; } -}; - -typedef DelegateList<Handler> DL; - -void multicast(DL &dl) { - for (DL::Snapshot snap(dl) ; snap.valid(); snap.next()) { - snap.get()->add(); - } -} - -void multicast_clear(DL &dl) { - DL::Snapshot snap(dl); - dl.clear(); - for (; snap.valid(); snap.next()) { - snap.get()->add(); - } -} - -//----------------------------------------------------------------------------- - -enum { - CMD_MULTICAST, - CMD_MULTICAST_CLEAR, - CMD_ADD, - CMD_REMOVE, - CMD_CLEAR, - CMD_WAIT_SNAP, - CMD_DO, - CMD_DONE, - CMD_EXIT -}; - -struct Command -{ - DL *dl; - int cmd; - int cnt; - Handler *handler; - Command(DL *dl_, int cmd_, int cnt_, Handler *handler_) noexcept - : dl(dl_), cmd(cmd_), cnt(cnt_), handler(handler_) {} - Command(const Command &rhs) noexcept - : dl(rhs.dl), cmd(rhs.cmd), cnt(rhs.cnt), handler(rhs.handler) {} - Command &operator=(const Command &rhs) noexcept { - memcpy(this, &rhs, sizeof(Command)); - return *this; - } - bool operator==(const Command &rhs) noexcept { - return memcmp(this, &rhs, sizeof(Command)) == 0; - } -}; - -Command -cmd_multicast(DL *dl) { - return Command(dl, CMD_MULTICAST, 0, 0); -} - -Command -cmd_multicast_clear(DL *dl) { - return Command(dl, CMD_MULTICAST_CLEAR, 0, 0); -} - -Command -cmd_add(DL *dl, Handler *handler) { - return Command(dl, CMD_ADD, 0, handler); -} - -Command -cmd_remove(DL *dl, Handler *handler) { - return Command(dl, CMD_REMOVE, 0, handler); -} - -Command -cmd_clear(DL *dl) { - return Command(dl, CMD_CLEAR, 0, 0); -} - -Command -cmd_wait_snap(DL *dl) { - return Command(dl, CMD_WAIT_SNAP, 0, 0); -} - -Command -cmd_do(int cnt) { - return Command(0, CMD_DO, cnt, 0); -} - -Command -cmd_done() { - return Command(0, CMD_DONE, 0, 0); -} - -Command -cmd_exit() { - return Command(0, CMD_EXIT, 0, 0); -} - -typedef std::vector<Command> CmdList; -typedef std::pair<Command, int> HistEntry; -typedef std::vector<HistEntry> HistList; - -//----------------------------------------------------------------------------- - -struct History { - Lock lock; - HistList list; - History() : lock(), list() {} - void add(const HistEntry &entry) { - LockGuard guard(lock); - list.push_back(entry); - } -}; - -//----------------------------------------------------------------------------- - -template <typename T> -class Queue { -private: - std::queue<T> _q; - Monitor _cond; - int _waitCnt; - Queue(const Queue &); - Queue &operator=(const Queue &); -public: - Queue() : _q(), _cond(), _waitCnt(0) {} - void enqueue(const T &entry) { - MonitorGuard guard(_cond); - _q.push(entry); - if (_waitCnt > 0) { - guard.signal(); - } - } - T dequeue() { - MonitorGuard guard(_cond); - CounterGuard cntGuard(_waitCnt); - while (_q.empty()) { - guard.wait(); - } - T tmp = _q.front(); - _q.pop(); - return tmp; - } - size_t size() const { return _q.size(); } -}; - -typedef Queue<CmdList> CmdListQueue; - -//----------------------------------------------------------------------------- - -class Actor : public FastOS_Runnable -{ -public: - enum { - STATE_INIT, - STATE_IDLE, - STATE_BUSY, - STATE_DONE - }; -private: - int _id; - History *_hist; - CmdListQueue _queue; - Monitor _cond; - int _state; - int _waitCnt; - int _opCnt; - bool _exit; - Actor(const Actor &); - Actor &operator=(const Actor &); - void setState(int state, MonitorGuard &guard); - void doneOp(const Command &cmd); - int perform(int cnt, int start, const CmdList &cmdList); -public: - Actor(int id, History *hist); - ~Actor(); - int getOpCnt() const { return _opCnt; } - int getState() const { return _state; } - void doIt(const CmdList &cmdList); - void doIt(const Command &cmd); - void waitState(int state); - void Run(FastOS_ThreadInterface *, void *) override; -}; - -Actor::Actor(int id, History *hist) - : _id(id), _hist(hist), _queue(), _cond(), _state(STATE_INIT), - _waitCnt(0), _opCnt(0), _exit(false) -{} -Actor::~Actor() {} - -void -Actor::setState(int state, MonitorGuard &guard) { - _state = state; - if (_waitCnt > 0) { - guard.broadcast(); - } -} - - -void -Actor::doneOp(const Command &cmd) -{ - ++_opCnt; - if (_hist != 0) { - _hist->add(HistEntry(cmd, _id)); - } -} - - -int -Actor::perform(int cnt, int start, const CmdList &cmdList) -{ - int doneIdx = cmdList.size(); - for (int i = 0; i < cnt; ++i) { - for (uint32_t idx = start; idx < cmdList.size(); ++idx) { - Command cmd = cmdList[idx]; - switch (cmd.cmd) { - case CMD_MULTICAST: - multicast(*cmd.dl); - doneOp(cmd); - break; - case CMD_MULTICAST_CLEAR: - multicast_clear(*cmd.dl); - doneOp(cmd); - break; - case CMD_ADD: - cmd.dl->add(cmd.handler); - doneOp(cmd); - break; - case CMD_REMOVE: - cmd.dl->remove(cmd.handler); - doneOp(cmd); - break; - case CMD_CLEAR: - cmd.dl->clear(); - doneOp(cmd); - break; - case CMD_WAIT_SNAP: - cmd.dl->waitSnapshots(); - doneOp(cmd); - break; - case CMD_DO: - idx = perform(cmd.cnt, idx + 1, cmdList); - break; - case CMD_DONE: - doneIdx = idx; - idx = cmdList.size(); - break; - case CMD_EXIT: - _exit = true; - return cmdList.size(); - break; - default: - LOG_ABORT("should not be reached"); // that does not seem to work - } - } - } - return doneIdx; -} - - -void -Actor::doIt(const CmdList &cmdList) -{ - MonitorGuard guard(_cond); - setState(STATE_BUSY, guard); - _queue.enqueue(cmdList); -} - - -void -Actor::doIt(const Command &cmd) -{ - CmdList cmdList; - cmdList.push_back(cmd); - doIt(cmdList); -} - - -void -Actor::waitState(int state) { - MonitorGuard guard(_cond); - CounterGuard cntGuard(_waitCnt); - while (_state != state) { - guard.wait(); - } -} - - -void -Actor::Run(FastOS_ThreadInterface *, void *) -{ - while (!_exit) { - { - MonitorGuard guard(_cond); - if (_queue.size() == 0) { - setState(STATE_IDLE, guard); - } - } - CmdList cmdList = _queue.dequeue(); - perform(1, 0, cmdList); - } - { - MonitorGuard guard(_cond); - setState(STATE_DONE, guard); - } -} - -} // namespace <unnamed> - -//----------------------------------------------------------------------------- - -void -Test::testEmpty() -{ - DL multicaster; - multicast(multicaster); - multicast_clear(multicaster); - DL::Snapshot empty_snap(multicaster); - EXPECT_TRUE(!empty_snap.valid()); -} - - -void -Test::testAdd() -{ - DL multicaster; - Handler h1; - Handler h2; - Handler h3; - Handler h4; - Handler h5; - - // ensure correct initial state - EXPECT_TRUE(h1.getNum() == 0); - EXPECT_TRUE(h2.getNum() == 0); - EXPECT_TRUE(h3.getNum() == 0); - EXPECT_TRUE(h4.getNum() == 0); - EXPECT_TRUE(h5.getNum() == 0); - - // test basic adding - multicaster.add(&h1); - multicast(multicaster); - multicaster.add(&h2); - multicast(multicaster); - multicaster.add(&h3); - multicast(multicaster); - multicaster.add(&h4); - multicast(multicaster); - multicaster.add(&h5); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 5); - EXPECT_TRUE(h2.getNum() == 4); - EXPECT_TRUE(h3.getNum() == 3); - EXPECT_TRUE(h4.getNum() == 2); - EXPECT_TRUE(h5.getNum() == 1); - - // duplicate adds - multicaster.add(&h1); - multicaster.add(&h1); - multicaster.add(&h1); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 6); - EXPECT_TRUE(h2.getNum() == 5); - EXPECT_TRUE(h3.getNum() == 4); - EXPECT_TRUE(h4.getNum() == 3); - EXPECT_TRUE(h5.getNum() == 2); -} - - -void -Test::testRemove() -{ - DL multicaster; - Handler h1; - Handler h2; - Handler h3; - Handler h4; - Handler h5; - - multicaster.add(&h1).add(&h2).add(&h3).add(&h4).add(&h5); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 1); - EXPECT_TRUE(h2.getNum() == 1); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 1); - EXPECT_TRUE(h5.getNum() == 1); - - // remove middle - multicaster.remove(&h3); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 2); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 2); - EXPECT_TRUE(h5.getNum() == 2); - - // remove head - multicaster.remove(&h1); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 3); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 3); - EXPECT_TRUE(h5.getNum() == 3); - - // remove tail - multicaster.remove(&h5); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 4); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 4); - EXPECT_TRUE(h5.getNum() == 3); - - // duplicate removes - multicaster.remove(&h1).remove(&h3).remove(&h5); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 5); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 5); - EXPECT_TRUE(h5.getNum() == 3); - - // remove all - multicaster.clear(); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 5); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 5); - EXPECT_TRUE(h5.getNum() == 3); -} - - -void -Test::testOneShot() -{ - DL multicaster; - Handler h1; - Handler h2; - Handler h3; - Handler h4; - Handler h5; - - // oneshot multicast removes handlers - multicaster.add(&h1).add(&h2).add(&h3).add(&h4).add(&h5); - multicast_clear(multicaster); - multicast(multicaster); - EXPECT_TRUE(h1.getNum() == 1); - EXPECT_TRUE(h2.getNum() == 1); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 1); - EXPECT_TRUE(h5.getNum() == 1); -} - - -void -Test::testMultiSnapshot() -{ - DL multicaster; - Handler h1; - Handler h2; - Handler h3; - Handler h4; - Handler h5; - - DL::Snapshot empty_snap(multicaster); - multicaster.add(&h1).add(&h2).add(&h3).add(&h4).add(&h5); - DL::Snapshot snap1(multicaster); - multicaster.remove(&h3); - DL::Snapshot snap2(multicaster); - multicaster.remove(&h1); - DL::Snapshot snap3(multicaster); - multicaster.remove(&h5); - DL::Snapshot snap4(multicaster); - - EXPECT_TRUE(!empty_snap.valid()); - for (; snap1.valid(); snap1.next()) { - snap1.get()->add(); - } - EXPECT_TRUE(h1.getNum() == 1); - EXPECT_TRUE(h2.getNum() == 1); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 1); - EXPECT_TRUE(h5.getNum() == 1); - for (; snap2.valid(); snap2.next()) { - snap2.get()->add(); - } - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 2); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 2); - EXPECT_TRUE(h5.getNum() == 2); - for (; snap3.valid(); snap3.next()) { - snap3.get()->add(); - } - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 3); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 3); - EXPECT_TRUE(h5.getNum() == 3); - for (; snap4.valid(); snap4.next()) { - snap4.get()->add(); - } - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 4); - EXPECT_TRUE(h3.getNum() == 1); - EXPECT_TRUE(h4.getNum() == 4); - EXPECT_TRUE(h5.getNum() == 3); -} - - -void -Test::testActors() -{ - FastOS_ThreadPool pool(65000); - History hist; - Actor a1(1, &hist); - Actor a2(2, &hist); - DL dl; - Handler h1; - Handler h2; - - ASSERT_TRUE(pool.NewThread(&a1, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a2, 0) != 0); - - { - CmdList prog; - prog.push_back(cmd_add(&dl, &h1)); - prog.push_back(cmd_multicast(&dl)); - prog.push_back(cmd_add(&dl, &h2)); - prog.push_back(cmd_multicast(&dl)); - a1.doIt(prog); - a1.waitState(Actor::STATE_IDLE); - } - - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 1); - - { - CmdList prog; - prog.push_back(cmd_remove(&dl, &h1)); - prog.push_back(cmd_multicast(&dl)); - prog.push_back(cmd_clear(&dl)); - prog.push_back(cmd_multicast(&dl)); - a2.doIt(prog); - a2.waitState(Actor::STATE_IDLE); - } - - EXPECT_TRUE(h1.getNum() == 2); - EXPECT_TRUE(h2.getNum() == 2); - - { - CmdList prog; - prog.push_back(cmd_add(&dl, &h1)); - prog.push_back(cmd_add(&dl, &h2)); - prog.push_back(cmd_multicast_clear(&dl)); - prog.push_back(cmd_multicast(&dl)); - a1.doIt(prog); - a1.waitState(Actor::STATE_IDLE); - } - - EXPECT_TRUE(h1.getNum() == 3); - EXPECT_TRUE(h2.getNum() == 3); - - { - CmdList prog; - prog.push_back(cmd_add(&dl, &h1)); - prog.push_back(cmd_add(&dl, &h2)); - prog.push_back(cmd_do(10)); - prog.push_back(cmd_do(10)); - prog.push_back(cmd_multicast(&dl)); - prog.push_back(cmd_done()); - prog.push_back(cmd_done()); - prog.push_back(cmd_exit()); - a2.doIt(prog); - a2.waitState(Actor::STATE_DONE); - } - - EXPECT_TRUE(h1.getNum() == 103); - EXPECT_TRUE(h2.getNum() == 103); - - EXPECT_TRUE(hist.list.size() == 114); - - EXPECT_TRUE(hist.list[0].first == cmd_add(&dl, &h1)); - EXPECT_TRUE(hist.list[1].first == cmd_multicast(&dl)); - EXPECT_TRUE(hist.list[2].first == cmd_add(&dl, &h2)); - EXPECT_TRUE(hist.list[3].first == cmd_multicast(&dl)); - for (int i = 0; i < 4; i++) { - EXPECT_TRUE(hist.list[i].second == 1); - } - - EXPECT_TRUE(hist.list[4].first == cmd_remove(&dl, &h1)); - EXPECT_TRUE(hist.list[5].first == cmd_multicast(&dl)); - EXPECT_TRUE(hist.list[6].first == cmd_clear(&dl)); - EXPECT_TRUE(hist.list[7].first == cmd_multicast(&dl)); - for (int i = 4; i < 8; i++) { - EXPECT_TRUE(hist.list[i].second == 2); - } - - EXPECT_TRUE(hist.list[8].first == cmd_add(&dl, &h1)); - EXPECT_TRUE(hist.list[9].first == cmd_add(&dl, &h2)); - EXPECT_TRUE(hist.list[10].first == cmd_multicast_clear(&dl)); - EXPECT_TRUE(hist.list[11].first == cmd_multicast(&dl)); - for (int i = 8; i < 12; i++) { - EXPECT_TRUE(hist.list[i].second == 1); - } - - EXPECT_TRUE(hist.list[12].first == cmd_add(&dl, &h1)); - EXPECT_TRUE(hist.list[13].first == cmd_add(&dl, &h2)); - EXPECT_TRUE(hist.list[12].second == 2); - EXPECT_TRUE(hist.list[13].second == 2); - - for (int i = 14; i < 114; i++) { - EXPECT_TRUE(hist.list[i].first == cmd_multicast(&dl)); - EXPECT_TRUE(hist.list[i].second == 2); - } - - a1.doIt(cmd_exit()); - a1.waitState(Actor::STATE_DONE); - - EXPECT_TRUE(a1.getOpCnt() == 8); - EXPECT_TRUE(a2.getOpCnt() == 106); -} - - -void -Test::stressTest() -{ - FastOS_ThreadPool pool(65000); - Actor a1(1, 0); - Actor a2(2, 0); - Actor a3(3, 0); - Actor a4(4, 0); - Actor a5(5, 0); - Actor a6(6, 0); - DL dl; - Handler h1; - Handler h2; - Handler h3; - Handler h4; - Handler h5; - int scale = 10000; - - ASSERT_TRUE(pool.NewThread(&a1, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a2, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a3, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a4, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a5, 0) != 0); - ASSERT_TRUE(pool.NewThread(&a6, 0) != 0); - - CmdList prog_multicast; - prog_multicast.push_back(cmd_do(10 * scale)); - prog_multicast.push_back(cmd_multicast(&dl)); - prog_multicast.push_back(cmd_done()); - prog_multicast.push_back(cmd_exit()); - - CmdList prog_wait_snap; - prog_wait_snap.push_back(cmd_do(10 * scale)); - prog_wait_snap.push_back(cmd_wait_snap(&dl)); - prog_wait_snap.push_back(cmd_done()); - prog_wait_snap.push_back(cmd_exit()); - - CmdList prog_add_remove_1; - prog_add_remove_1.push_back(cmd_do(scale)); - prog_add_remove_1.push_back(cmd_add(&dl, &h1)); - prog_add_remove_1.push_back(cmd_add(&dl, &h3)); - prog_add_remove_1.push_back(cmd_remove(&dl, &h2)); - prog_add_remove_1.push_back(cmd_remove(&dl, &h4)); - prog_add_remove_1.push_back(cmd_add(&dl, &h4)); - prog_add_remove_1.push_back(cmd_add(&dl, &h2)); - prog_add_remove_1.push_back(cmd_remove(&dl, &h5)); - prog_add_remove_1.push_back(cmd_remove(&dl, &h3)); - prog_add_remove_1.push_back(cmd_add(&dl, &h5)); - prog_add_remove_1.push_back(cmd_remove(&dl, &h1)); - prog_add_remove_1.push_back(cmd_done()); - prog_add_remove_1.push_back(cmd_exit()); - - CmdList prog_add_remove_2; - prog_add_remove_2.push_back(cmd_do(scale)); - prog_add_remove_2.push_back(cmd_add(&dl, &h5)); - prog_add_remove_2.push_back(cmd_add(&dl, &h4)); - prog_add_remove_2.push_back(cmd_remove(&dl, &h1)); - prog_add_remove_2.push_back(cmd_remove(&dl, &h3)); - prog_add_remove_2.push_back(cmd_add(&dl, &h1)); - prog_add_remove_2.push_back(cmd_remove(&dl, &h2)); - prog_add_remove_2.push_back(cmd_add(&dl, &h2)); - prog_add_remove_2.push_back(cmd_add(&dl, &h3)); - prog_add_remove_2.push_back(cmd_remove(&dl, &h5)); - prog_add_remove_2.push_back(cmd_remove(&dl, &h4)); - prog_add_remove_2.push_back(cmd_done()); - prog_add_remove_2.push_back(cmd_exit()); - - CmdList prog_add_remove_3; - prog_add_remove_3.push_back(cmd_do(scale)); - prog_add_remove_3.push_back(cmd_add(&dl, &h3)); - prog_add_remove_3.push_back(cmd_remove(&dl, &h4)); - prog_add_remove_3.push_back(cmd_remove(&dl, &h3)); - prog_add_remove_3.push_back(cmd_add(&dl, &h5)); - prog_add_remove_3.push_back(cmd_add(&dl, &h2)); - prog_add_remove_3.push_back(cmd_remove(&dl, &h2)); - prog_add_remove_3.push_back(cmd_add(&dl, &h1)); - prog_add_remove_3.push_back(cmd_add(&dl, &h4)); - prog_add_remove_3.push_back(cmd_remove(&dl, &h1)); - prog_add_remove_3.push_back(cmd_remove(&dl, &h5)); - prog_add_remove_3.push_back(cmd_done()); - prog_add_remove_3.push_back(cmd_exit()); - - a1.doIt(prog_multicast); - a2.doIt(prog_multicast); - a3.doIt(prog_wait_snap); - a4.doIt(prog_add_remove_1); - a5.doIt(prog_add_remove_2); - a6.doIt(prog_add_remove_3); - - a1.waitState(Actor::STATE_DONE); - a2.waitState(Actor::STATE_DONE); - a3.waitState(Actor::STATE_DONE); - a4.waitState(Actor::STATE_DONE); - a5.waitState(Actor::STATE_DONE); - a6.waitState(Actor::STATE_DONE); - - EXPECT_TRUE(a1.getOpCnt() == 10 * scale); - EXPECT_TRUE(a2.getOpCnt() == 10 * scale); - EXPECT_TRUE(a3.getOpCnt() == 10 * scale); - EXPECT_TRUE(a4.getOpCnt() == 10 * scale); - EXPECT_TRUE(a5.getOpCnt() == 10 * scale); - EXPECT_TRUE(a6.getOpCnt() == 10 * scale); -} - - -void -Test::testWaitSnapshots() -{ - FastOS_ThreadPool pool(65000); - Actor a1(1, 0); - DL dl; - std::unique_ptr<DL::Snapshot> s1; - std::unique_ptr<DL::Snapshot> s2; - ASSERT_TRUE(pool.NewThread(&a1, 0) != 0); - s1.reset(new DL::Snapshot(dl)); // create snap 1 - a1.doIt(cmd_wait_snap(&dl)); // wait for snaps - std::this_thread::sleep_for(1s); - EXPECT_TRUE(a1.getState() == Actor::STATE_BUSY); // still waiting... - s2.reset(new DL::Snapshot(dl)); // create snap 2 - s1.reset(); // destroy snap 1 - std::this_thread::sleep_for(1s); - EXPECT_TRUE(a1.getState() == Actor::STATE_IDLE); // wait done! - a1.doIt(cmd_exit()); - a1.waitState(Actor::STATE_DONE); - s2.reset(); // destroy snap 2 - EXPECT_TRUE(a1.getOpCnt() == 1); -} - -//----------------------------------------------------------------------------- - -struct Foo { void completeBarrier() {} }; - -int -Test::Main() -{ - TEST_INIT("delegatelist_test"); - LOG(info, "Lock size: %4zu bytes", sizeof(Lock)); - LOG(info, "ArrayQueue size: %4zu bytes", sizeof(ArrayQueue<Foo>)); - LOG(info, "std::vector size: %4zu bytes", sizeof(std::vector<Foo>)); - LOG(info, "EventBarrier size: %4zu bytes", sizeof(EventBarrier<Foo>)); - LOG(info, "DelegateList size: %4zu bytes", sizeof(DelegateList<Foo>)); - - testEmpty(); - testAdd(); - testRemove(); - testOneShot(); - testMultiSnapshot(); - - TEST_FLUSH(); - testActors(); - testWaitSnapshots(); - - TEST_FLUSH(); - stressTest(); - TEST_DONE(); -} - -TEST_APPHOOK(Test); diff --git a/vespalib/src/tests/rwlock/.gitignore b/vespalib/src/tests/rwlock/.gitignore deleted file mode 100644 index 3ba74c11b14..00000000000 --- a/vespalib/src/tests/rwlock/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.depend -Makefile -rwlock_test -vespalib_rwlock_test_app diff --git a/vespalib/src/tests/rwlock/CMakeLists.txt b/vespalib/src/tests/rwlock/CMakeLists.txt deleted file mode 100644 index 2eda95a200c..00000000000 --- a/vespalib/src/tests/rwlock/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -vespa_add_executable(vespalib_rwlock_test_app TEST - SOURCES - rwlock_test.cpp - DEPENDS - vespalib -) -vespa_add_test(NAME vespalib_rwlock_test_app COMMAND vespalib_rwlock_test_app) diff --git a/vespalib/src/tests/rwlock/rwlock_test.cpp b/vespalib/src/tests/rwlock/rwlock_test.cpp deleted file mode 100644 index 66e73c3a5d9..00000000000 --- a/vespalib/src/tests/rwlock/rwlock_test.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// 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/rwlock.h> - -using namespace vespalib; - -class RWLockTest : public TestApp -{ -public: - int Main() override; - static RWLockReader rbvReader(RWLock & lock) { RWLockReader r(lock); return r; } - static RWLockWriter rbvWriter(RWLock & lock) { RWLockWriter r(lock); return r; } -}; - - -int -RWLockTest::Main() -{ - TEST_INIT("rwlock_test"); - - RWLock lock; - EXPECT_TRUE(lock._givenLocks == 0); - { - EXPECT_TRUE(lock._givenLocks == 0); - RWLockReader r1(lock); - EXPECT_TRUE(lock._givenLocks == 1); - RWLockReader r2(lock); - EXPECT_TRUE(lock._givenLocks == 2); - RWLockReader r3(lock); - EXPECT_TRUE(lock._givenLocks == 3); - } - EXPECT_TRUE(lock._givenLocks == 0); - { - EXPECT_TRUE(lock._givenLocks == 0); - RWLockWriter w(lock); - EXPECT_TRUE(lock._givenLocks == -1); - } - EXPECT_TRUE(lock._givenLocks == 0); - { - RWLockReader rbv(rbvReader(lock)); - EXPECT_TRUE(lock._givenLocks == 1); - RWLockReader copy(rbv); - EXPECT_TRUE(lock._givenLocks == 1); - RWLockReader copy2(copy); - EXPECT_TRUE(lock._givenLocks == 1); - } - EXPECT_TRUE(lock._givenLocks == 0); - { - RWLock lock2; - RWLockReader copy(rbvReader(lock)); - EXPECT_TRUE(lock._givenLocks == 1); - RWLockReader copy2(rbvReader(lock2)); - EXPECT_TRUE(lock._givenLocks == 1); - EXPECT_TRUE(lock2._givenLocks == 1); - RWLockReader rbv(rbvReader(lock)); - EXPECT_TRUE(lock._givenLocks == 2); - copy=rbv; - EXPECT_TRUE(lock._givenLocks == 1); - copy2=copy; - EXPECT_TRUE(lock2._givenLocks == 0); - EXPECT_TRUE(lock._givenLocks == 1); - } - EXPECT_TRUE(lock._givenLocks == 0); - { - RWLockWriter rbv(rbvWriter(lock)); - EXPECT_TRUE(lock._givenLocks == -1); - RWLockWriter copy(rbv); - EXPECT_TRUE(lock._givenLocks == -1); - RWLockWriter copy2(copy); - EXPECT_TRUE(lock._givenLocks == -1); - } - EXPECT_TRUE(lock._givenLocks == 0); - - TEST_DONE(); -} - -TEST_APPHOOK(RWLockTest) diff --git a/vespalib/src/tests/sync/sync_test.cpp b/vespalib/src/tests/sync/sync_test.cpp index c8888bc8e54..0925ce060a0 100644 --- a/vespalib/src/tests/sync/sync_test.cpp +++ b/vespalib/src/tests/sync/sync_test.cpp @@ -3,6 +3,44 @@ #include <vespa/vespalib/testkit/testapp.h> #include <vespa/vespalib/util/sync.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 Lock &lock) + : _guard(*lock._mutex, std::try_to_lock), _cond(nullptr) + {} + 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()); } @@ -18,7 +56,7 @@ private: LockGuard lockMonitor() { return LockGuard(_monitor); } MonitorGuard obtainMonitor() { return MonitorGuard(_monitor); } public: - ~Test(); + ~Test() override; void testCountDownLatch(); int Main() override; }; @@ -139,97 +177,6 @@ Test::Main() MonitorGuard guard(monitor); CHECK_LOCKED(monitor); } - // TryLock hands the lock over to a LockGuard/MonitorGuard - { - Lock lock; - CHECK_UNLOCKED(lock); - TryLock a(lock); - CHECK_LOCKED(lock); - if (a.hasLock()) { - LockGuard guard(std::move(a)); - CHECK_LOCKED(lock); - } - CHECK_UNLOCKED(lock); - } - { - Monitor mon; - CHECK_UNLOCKED(mon); - TryLock a(mon); - CHECK_LOCKED(mon); - if (a.hasLock()) { - LockGuard guard(std::move(a)); - CHECK_LOCKED(mon); - } - CHECK_UNLOCKED(mon); - } - { - Monitor mon; - CHECK_UNLOCKED(mon); - TryLock a(mon); - CHECK_LOCKED(mon); - if (a.hasLock()) { - MonitorGuard guard(std::move(a)); - CHECK_LOCKED(mon); - } - CHECK_UNLOCKED(mon); - } - { - Lock lock; - - CHECK_UNLOCKED(lock); - TryLock a(lock); - CHECK_LOCKED(lock); - TryLock b(lock); - CHECK_LOCKED(lock); - - EXPECT_TRUE(a.hasLock()); - EXPECT_TRUE(!b.hasLock()); - { - CHECK_LOCKED(lock); - EXPECT_TRUE(a.hasLock()); - LockGuard guard(std::move(a)); - EXPECT_TRUE(!a.hasLock()); - CHECK_LOCKED(lock); - } - CHECK_UNLOCKED(lock); - } - // TryLock will unlock when exiting scope if lock was not passed on - { - Lock lock; - Monitor mon; - CHECK_UNLOCKED(lock); - CHECK_UNLOCKED(mon); - { - TryLock a(lock); - EXPECT_TRUE(a.hasLock()); - TryLock b(mon); - EXPECT_TRUE(b.hasLock()); - CHECK_LOCKED(lock); - CHECK_LOCKED(mon); - } - CHECK_UNLOCKED(lock); - CHECK_UNLOCKED(mon); - } - // TryLock explicitt unlock of lock - { - Lock lock; - TryLock tl(lock); - EXPECT_TRUE(tl.hasLock()); - tl.unlock(); - EXPECT_FALSE(tl.hasLock()); - tl.unlock(); - EXPECT_FALSE(tl.hasLock()); - } - // TryLock explicitt unlock of monitor - { - Monitor lock; - TryLock tl(lock); - EXPECT_TRUE(tl.hasLock()); - tl.unlock(); - EXPECT_FALSE(tl.hasLock()); - tl.unlock(); - EXPECT_FALSE(tl.hasLock()); - } // LockGuard/MonitorGuard have destructive move { Lock lock; diff --git a/vespalib/src/vespa/vespalib/data/memorydatastore.cpp b/vespalib/src/vespa/vespalib/data/memorydatastore.cpp index df1b68cff12..1f8c72a5a64 100644 --- a/vespalib/src/vespa/vespalib/data/memorydatastore.cpp +++ b/vespalib/src/vespa/vespalib/data/memorydatastore.cpp @@ -5,8 +5,9 @@ namespace vespalib { using alloc::Alloc; +using LockGuard = std::lock_guard<std::mutex>; -MemoryDataStore::MemoryDataStore(Alloc && initialAlloc, Lock * lock) : +MemoryDataStore::MemoryDataStore(Alloc && initialAlloc, std::mutex * lock) : _buffers(), _writePos(0), _lock(lock) diff --git a/vespalib/src/vespa/vespalib/data/memorydatastore.h b/vespalib/src/vespa/vespalib/data/memorydatastore.h index 2d02bfb107c..fa6113279da 100644 --- a/vespalib/src/vespa/vespalib/data/memorydatastore.h +++ b/vespalib/src/vespa/vespalib/data/memorydatastore.h @@ -3,8 +3,8 @@ #include <vespa/vespalib/util/alloc.h> #include <vespa/vespalib/util/array.h> -#include <vespa/vespalib/util/sync.h> #include <vector> +#include <mutex> namespace vespalib { @@ -24,7 +24,7 @@ public: private: void * _data; }; - MemoryDataStore(alloc::Alloc && initialAlloc=alloc::Alloc::alloc(256), Lock * lock=nullptr); + MemoryDataStore(alloc::Alloc && initialAlloc=alloc::Alloc::alloc(256), std::mutex * lock=nullptr); MemoryDataStore(const MemoryDataStore &) = delete; MemoryDataStore & operator = (const MemoryDataStore &) = delete; ~MemoryDataStore(); @@ -41,7 +41,7 @@ public: private: std::vector<alloc::Alloc> _buffers; size_t _writePos; - Lock * _lock; + std::mutex * _lock; }; class VariableSizeVector diff --git a/vespalib/src/vespa/vespalib/testkit/test_master.cpp b/vespalib/src/vespa/vespalib/testkit/test_master.cpp index 4b673d0ee0d..60e51ac3a91 100644 --- a/vespalib/src/vespa/vespalib/testkit/test_master.cpp +++ b/vespalib/src/vespa/vespalib/testkit/test_master.cpp @@ -37,7 +37,7 @@ __thread TestMaster::ThreadState *TestMaster::_threadState = 0; TestMaster::TraceItem::~TraceItem() = default; TestMaster::ThreadState & -TestMaster::threadState(const vespalib::LockGuard &) +TestMaster::threadState(const lock_guard &) { if (_threadState == 0) { std::ostringstream threadName; @@ -55,7 +55,7 @@ TestMaster::threadState() return *_threadState; } { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); return threadState(guard); } } @@ -63,7 +63,7 @@ TestMaster::threadState() //----------------------------------------------------------------------------- void -TestMaster::checkFailed(const vespalib::LockGuard &guard, +TestMaster::checkFailed(const lock_guard &guard, const char *file, uint32_t line, const char *str) { ThreadState &thread = threadState(guard); @@ -81,7 +81,7 @@ TestMaster::checkFailed(const vespalib::LockGuard &guard, } void -TestMaster::printDiff(const vespalib::LockGuard &guard, +TestMaster::printDiff(const lock_guard &guard, const std::string &text, const std::string &file, uint32_t line, const std::string &lhs, const std::string &rhs) { @@ -106,7 +106,7 @@ TestMaster::printDiff(const vespalib::LockGuard &guard, } void -TestMaster::handleFailure(const vespalib::LockGuard &guard, bool fatal) +TestMaster::handleFailure(const lock_guard &guard, bool fatal) { ThreadState &thread = threadState(guard); if (fatal) { @@ -120,7 +120,7 @@ TestMaster::handleFailure(const vespalib::LockGuard &guard, bool fatal) } void -TestMaster::closeDebugFiles(const vespalib::LockGuard &) +TestMaster::closeDebugFiles(const lock_guard &) { if (_state.lhsFile != NULL) { fclose(_state.lhsFile); @@ -133,7 +133,7 @@ TestMaster::closeDebugFiles(const vespalib::LockGuard &) } void -TestMaster::importThreads(const vespalib::LockGuard &) +TestMaster::importThreads(const lock_guard &) { size_t importCnt = 0; for (size_t i = 0; i < _threadStorage.size(); ++i) { @@ -149,7 +149,7 @@ TestMaster::importThreads(const vespalib::LockGuard &) } bool -TestMaster::reportConclusion(const vespalib::LockGuard &) +TestMaster::reportConclusion(const lock_guard &) { bool ok = (_state.failCnt == 0); fprintf(stderr, "%s: info: summary --- %zu check(s) passed --- %zu check(s) failed\n", @@ -175,7 +175,7 @@ TestMaster::TestMaster() void TestMaster::init(const char *name) { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); _name = skip_path(name); fprintf(stderr, "%s: info: running test suite '%s'\n", _name.c_str(), _name.c_str()); } @@ -183,7 +183,7 @@ TestMaster::init(const char *name) std::string TestMaster::getName() { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); return _name; } @@ -226,7 +226,7 @@ TestMaster::setThreadIgnore(bool ignore) size_t revertCnt = (thread.failCnt - thread.preIgnoreFailCnt); thread.failCnt = thread.preIgnoreFailCnt; if (revertCnt > 0) { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); assert(_state.failCnt >= revertCnt); _state.failCnt -= revertCnt; } @@ -272,7 +272,7 @@ TestMaster::getThreadFailCnt() TestMaster::Progress TestMaster::getProgress() { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); return Progress(_state.passCnt, _state.failCnt); } @@ -280,7 +280,7 @@ void TestMaster::openDebugFiles(const std::string &lhsFile, const std::string &rhsFile) { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); closeDebugFiles(guard); _state.lhsFile = fopen(lhsFile.c_str(), "w"); _state.rhsFile = fopen(rhsFile.c_str(), "w"); @@ -318,7 +318,7 @@ TestMaster::check(bool rc, const char *file, uint32_t line, return true; } { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); checkFailed(guard, file, line, str); handleFailure(guard, fatal); } @@ -330,7 +330,7 @@ TestMaster::flush(const char *file, uint32_t line) { ThreadState &thread = threadState(); if (thread.passCnt > 0) { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); _state.passCnt += thread.passCnt; fprintf(stderr, "%s: info: flushed %zu passed check(s) from thread '%s' (%s:%d)\n", _name.c_str(), thread.passCnt, thread.name.c_str(), skip_path(file), line); @@ -349,7 +349,7 @@ TestMaster::trace(const char *file, uint32_t line) bool TestMaster::discardFailedChecks(size_t failCnt) { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); ThreadState &thread = threadState(guard); if (failCnt == _state.failCnt) { fprintf(stderr, "%s: info: discarding %zu failed check(s)\n", _name.c_str(), _state.failCnt); @@ -367,7 +367,7 @@ TestMaster::discardFailedChecks(size_t failCnt) bool TestMaster::fini() { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); closeDebugFiles(guard); importThreads(guard); return reportConclusion(guard); diff --git a/vespalib/src/vespa/vespalib/testkit/test_master.h b/vespalib/src/vespa/vespalib/testkit/test_master.h index a9dc5ebb3a2..c20982b994d 100644 --- a/vespalib/src/vespa/vespalib/testkit/test_master.h +++ b/vespalib/src/vespa/vespalib/testkit/test_master.h @@ -2,10 +2,10 @@ #pragma once -#include <vespa/vespalib/util/sync.h> #include <string> #include <vector> #include <memory> +#include <mutex> namespace vespalib { @@ -69,24 +69,25 @@ private: }; private: - vespalib::Lock _lock; + std::mutex _lock; std::string _name; std::string _path_prefix; SharedState _state; std::vector<std::unique_ptr<ThreadState> > _threadStorage; + using lock_guard = std::lock_guard<std::mutex>; private: - ThreadState &threadState(const vespalib::LockGuard &); + ThreadState &threadState(const lock_guard &); ThreadState &threadState(); - void checkFailed(const vespalib::LockGuard &, + void checkFailed(const lock_guard &, const char *file, uint32_t line, const char *str); - void printDiff(const vespalib::LockGuard &, + void printDiff(const lock_guard &, const std::string &text, const std::string &file, uint32_t line, const std::string &lhs, const std::string &rhs); - void handleFailure(const vespalib::LockGuard &, bool do_abort); - void closeDebugFiles(const vespalib::LockGuard &); - void importThreads(const vespalib::LockGuard &); - bool reportConclusion(const vespalib::LockGuard &); + void handleFailure(const lock_guard &, bool do_abort); + void closeDebugFiles(const lock_guard &); + void importThreads(const lock_guard &); + bool reportConclusion(const lock_guard &); private: TestMaster(); diff --git a/vespalib/src/vespa/vespalib/testkit/test_master.hpp b/vespalib/src/vespa/vespalib/testkit/test_master.hpp index f165458c9aa..245c128b788 100644 --- a/vespalib/src/vespa/vespalib/testkit/test_master.hpp +++ b/vespalib/src/vespa/vespalib/testkit/test_master.hpp @@ -33,7 +33,7 @@ TestMaster::compare(const char *file, uint32_t line, lhs << a; rhs << b; { - vespalib::LockGuard guard(_lock); + lock_guard guard(_lock); checkFailed(guard, file, line, str.c_str()); printDiff(guard, str, file, line, lhs.str(), rhs.str()); handleFailure(guard, fatal); diff --git a/vespalib/src/vespa/vespalib/util/CMakeLists.txt b/vespalib/src/vespa/vespalib/util/CMakeLists.txt index fd645f9008c..ea2189fc3a8 100644 --- a/vespalib/src/vespa/vespalib/util/CMakeLists.txt +++ b/vespalib/src/vespa/vespalib/util/CMakeLists.txt @@ -40,7 +40,6 @@ vespa_add_library(vespalib_vespalib_util OBJECT reusable_set_pool.cpp runnable.cpp runnable_pair.cpp - rwlock.cpp sequence.cpp sha1.cpp sig_catch.cpp diff --git a/vespalib/src/vespa/vespalib/util/alloc.cpp b/vespalib/src/vespa/vespalib/util/alloc.cpp index 5ae499f5482..745fb50db03 100644 --- a/vespalib/src/vespa/vespalib/util/alloc.cpp +++ b/vespalib/src/vespa/vespalib/util/alloc.cpp @@ -4,11 +4,11 @@ #include <vespa/vespalib/util/stringfmt.h> #include <vespa/vespalib/util/exceptions.h> #include <vespa/vespalib/util/backtrace.h> -#include <vespa/vespalib/util/sync.h> #include <map> #include <atomic> #include <unordered_map> #include <cassert> +#include <mutex> #include <vespa/fastos/file.h> #include <unistd.h> @@ -25,7 +25,7 @@ int _G_HugeFlags = 0; const size_t _G_pageSize = getpagesize(); size_t _G_MMapLogLimit = std::numeric_limits<size_t>::max(); size_t _G_MMapNoCoreLimit = std::numeric_limits<size_t>::max(); -Lock _G_lock; +std::mutex _G_lock; std::atomic<size_t> _G_mmapCount(0); size_t @@ -362,7 +362,7 @@ MMapAllocator::salloc(size_t sz, void * wantedAddress) } #endif if (sz >= _G_MMapLogLimit) { - LockGuard guard(_G_lock); + std::lock_guard guard(_G_lock); _G_HugeMappings[buf] = MMapInfo(mmapId, sz, stackTrace); LOG(info, "%ld mappings of accumulated size %ld", _G_HugeMappings.size(), sum(_G_HugeMappings)); } @@ -412,7 +412,7 @@ void MMapAllocator::sfree(PtrAndSize alloc) retval = munmap(alloc.first, alloc.second); assert(retval == 0); if (alloc.second >= _G_MMapLogLimit) { - LockGuard guard(_G_lock); + std::lock_guard guard(_G_lock); MMapInfo info = _G_HugeMappings[alloc.first]; assert(alloc.second == info._sz); _G_HugeMappings.erase(alloc.first); diff --git a/vespalib/src/vespa/vespalib/util/delegatelist.hpp b/vespalib/src/vespa/vespalib/util/delegatelist.hpp deleted file mode 100644 index 716474f66f7..00000000000 --- a/vespalib/src/vespa/vespalib/util/delegatelist.hpp +++ /dev/null @@ -1,309 +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 "eventbarrier.hpp" -#include "sync.h" - -namespace vespalib { - -/** - * Data structure for robust event multi-casting in a multi-threaded - * environment. The state tracked by this class can be modeled as a - * set of bald object pointers; the delegates. All interaction with - * the delegates is done through a snapshot of the delegate list. The - * list may be modified at any time. Modifications will not be visible - * to already existing snapshots. A separate method may be used to - * wait for the destruction of all currently active snapshots. This - * synchronization will ensure visibility of any previous - * modifications to the delegate list. State snapshotting is - * implemented with reference counted immutable lists. Snapshot - * waiting is implemented using event barriers. - **/ -template <typename T> -class DelegateList -{ -private: - /** - * Simple class used to synchronize with the completion of an - * event barrier by coupling barrier completion to a gate. - **/ - struct Sync - { - Gate gate; - Sync() : gate() {} - void completeBarrier() { gate.countDown(); } - }; - - /** - * Inner structure used when keeping track of a set of delegates. - **/ - struct Node { - uint32_t refcnt; // the number of incoming pointers to this node. - T *delegate; // the delegate tracked by this node. - Node *next; // the next node in this list. - }; - - Lock _lock; // lock protecting access to this object - Node *_head; // head of current list of delegates - EventBarrier<Sync> _barrier; // object used to resolve event barriers - Node *_freeNodes; // a list of recyclable internal nodes - int _activeNodes; // number of internal nodes currently in use - ArrayQueue<T*> _stack; // explicit stack for cheap 'recursion' - - /** - * Allocate a new node and initialize it with the given data - * members. Nodes are recycled internally by this object to reduce - * overhead. - * - * @return the new node - * @param delegate the delegate for the new node - * @param next the next pointer for the new node - **/ - Node *allocNode(T *delegate, Node *next) { - Node *node = _freeNodes; - if (node != 0) { - _freeNodes = node->next; - } else { - node = new Node(); - } - node->refcnt = 1; - node->delegate = delegate; - node->next = next; - ++_activeNodes; - return node; - } - - /** - * Copy a list of nodes. This will increase the reference count of - * the list. - * - * @return the copy of the list - * @param list the list to copy - **/ - Node *copyList(Node *list) { - if (list != 0) { - ++list->refcnt; - } - return list; - } - - /** - * Free a list of nodes. This will decrease the reference count of - * the list. Any nodes no longer in use will be put back on the - * internal free list. - * - * @return 0 - * @param list the list to free - **/ - Node *freeList(Node *list) { - while (list != 0 && --list->refcnt == 0) { - Node *node = list; - list = node->next; - node->next = _freeNodes; - _freeNodes = node; - --_activeNodes; - } - return 0; - } - - DelegateList(const DelegateList &); - DelegateList &operator=(const DelegateList &); - -public: - /** - * A snapshot of a delegate list. The only way to access the - * delegates kept by a delegate list is to create a snapshot of - * it. The snapshot lets the user traverse the list of delegates, - * accessing each of them in turn. The existence of a snapshot is - * used by the delegate list to identify that someone is observing - * the delegate list in a specific state. Snapshots should be - * created on the stack in a scope as close as possible to the - * code actually accessing the delegates. The delegate list itself - * may not be destructed until all snapshots of that list have - * been destructed. - **/ - class Snapshot - { - private: - DelegateList &_list; // the parent object - Node *_head; // head of the snapshotted list - Node *_node; // current position within snapshot - uint32_t _token; // token used for barrier resolving - - Snapshot(const Snapshot &); - Snapshot &operator=(const Snapshot &); - public: - /** - * Create a snapshot of the given delegate list. The snapshots - * current position will be set to the first delegate part of - * the snapshot. - * - * @param list the delegate list we are snapshotting - **/ - explicit Snapshot(DelegateList &list) : _list(list) { - LockGuard guard(list._lock); - _head = list.copyList(list._head); - _node = _head; - _token = list._barrier.startEvent(); - } - - /** - * Destructing a snapshot will tell the delegate list that we - * are no longer accessing the list in the state observed by - * the snapshot. - **/ - ~Snapshot() { - LockGuard guard(_list._lock); - _list.freeList(_head); - _list._barrier.completeEvent(_token); - } - - /** - * Check whether the current delegate is valid. A snapshot - * becomes invalid after the user has stepped through all - * delegates part of the snapshot using the 'next' method. - * - * @return true if the current delegate is valid - **/ - bool valid() const { - return (_node != 0); - } - - /** - * Step to the next delegate. This method may only be called - * if the 'valid' method returns true. - **/ - void next() { - _node = _node->next; - } - - /** - * Get the current delegate. This method may only be called if - * the 'valid' method returns true. - * - * @return current delegate - **/ - T *get() const { - return _node->delegate; - } - }; - - /** - * Create an initially empty delegate list. - **/ - DelegateList() - : _lock(), - _head(0), - _barrier(), - _freeNodes(0), - _activeNodes(0), - _stack() - { - } - - /** - * The destructor will clean up internal memory usage. The - * delegate list itself does not need to be empty when it is - * deleted. However, there may be no active snapshots of it and - * no-one may be waiting for snapshot destruction. - **/ - ~DelegateList() { - freeList(_head); - assert(_barrier.countBarriers() == 0); - assert(_barrier.countEvents() == 0); - assert(_activeNodes == 0); - while (_freeNodes != 0) { - Node *node = _freeNodes; - _freeNodes = node->next; - delete node; - } - } - - /** - * Add a delegate to this list. Adding a delegate that is already - * in the list will have no effect. - * - * @return this object, for chaining - * @param delegate the delegate to add - **/ - DelegateList &add(T *delegate) { - LockGuard guard(_lock); - Node *node = _head; - while (node != 0 && node->delegate != delegate) { - node = node->next; - } - if (node == 0) { - _head = allocNode(delegate, _head); - } - return *this; - } - - /** - * Remove a delegate from this list. - * - * @return this object, for chaining - * @param delegate the delegate to remove - **/ - DelegateList &remove(T *delegate) { - LockGuard guard(_lock); - _stack.clear(); - Node *node = _head; - while (node != 0 && node->delegate != delegate) { - _stack.push(node->delegate); - node = node->next; - } - if (node != 0) { // delegate found in list - node = copyList(node->next); - while (!_stack.empty()) { - try { - node = allocNode(_stack.back(), node); - } catch (...) { - freeList(node); - throw; - } - _stack.popBack(); - } - freeList(_head); - _head = node; - } - return *this; - } - - /** - * Remove all delegates currently in this list. - * - * @return this object, for chaining - **/ - DelegateList &clear() { - LockGuard guard(_lock); - _head = freeList(_head); - return *this; - } - - /** - * Wait for the destruction of all currently active snapshots of - * this list. This method will block until all relevant snapshots - * are destructed. The creation of new snapshots will not - * interfere with the completion of this method. This method is - * used to enforce visibility between threads; after this method - * returns, any modifications performed on the list before this - * method was invoked will be visible to all threads. - * - * @return this object, for chaining - **/ - DelegateList &waitSnapshots() { - Sync sync; - { - LockGuard guard(_lock); - if (!_barrier.startBarrier(sync)) { - return *this; - } - } - sync.gate.await(); - return *this; - } -}; - -} // namespace vespalib - diff --git a/vespalib/src/vespa/vespalib/util/ptrholder.h b/vespalib/src/vespa/vespalib/util/ptrholder.h index 1c06e5c53e6..be528ba25db 100644 --- a/vespalib/src/vespa/vespalib/util/ptrholder.h +++ b/vespalib/src/vespa/vespalib/util/ptrholder.h @@ -4,7 +4,7 @@ #include <algorithm> #include <memory> -#include <vespa/vespalib/util/sync.h> +#include <mutex> namespace vespalib { @@ -29,11 +29,11 @@ class PtrHolder private: std::shared_ptr<T> _current; std::shared_ptr<T> _next; - mutable Lock _lock; - - PtrHolder(const PtrHolder &); - PtrHolder &operator=(const PtrHolder &); + mutable std::mutex _lock; + using LockGuard = std::lock_guard<std::mutex>; public: + PtrHolder(const PtrHolder &) = delete; + PtrHolder &operator=(const PtrHolder &) = delete; /** * @brief Create an empty PtrHolder with both current and new * pointers set to 0 @@ -53,14 +53,14 @@ public: * * @return true if the current value is set (not 0) **/ - bool hasValue() const { return (_current.get() != nullptr); } + bool hasValue() const { return bool(_current); } /** * @brief Check if the new value is set (not 0) * * @return true if the new value is set (not 0) **/ - bool hasNewValue() const { return (_next.get() != nullptr); } + bool hasNewValue() const { return bool(_next); } /** * @brief Set a new value diff --git a/vespalib/src/vespa/vespalib/util/rwlock.cpp b/vespalib/src/vespa/vespalib/util/rwlock.cpp deleted file mode 100644 index fc3799bc1d0..00000000000 --- a/vespalib/src/vespa/vespalib/util/rwlock.cpp +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. - -#include "rwlock.h" -#include <cassert> - -namespace vespalib { - -void RWLock::lockRead() { - MonitorGuard guard(_monitor); - CounterGuard waitCnt(_waitingReaders); - while (_givenLocks == -1 || _waitingWriters > 0) { - guard.wait(); - } - ++_givenLocks; -} - -void RWLock::unlockRead() { - MonitorGuard guard(_monitor); - assert(_givenLocks > 0); - if (--_givenLocks == 0 && _waitingWriters > 0) { - guard.broadcast(); - } -} - -void RWLock::lockWrite() { - MonitorGuard guard(_monitor); - CounterGuard waitCnt(_waitingWriters); - while (_givenLocks != 0) { - guard.wait(); - } - _givenLocks = -1; -} - -void RWLock::unlockWrite() { - MonitorGuard guard(_monitor); - assert(_givenLocks == -1); - _givenLocks = 0; - if (_waitingReaders > 0 || _waitingWriters > 0) { - guard.broadcast(); - } -} - -RWLock * -RWLockReader::stealLock() { - RWLock * ret(_lock); - assert(ret != nullptr); - _lock = nullptr; - return ret; -} - -RWLock * -RWLockWriter::stealLock() { - RWLock * ret(_lock); - assert(ret != nullptr); - _lock = nullptr; - return ret; -} - -} // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/util/rwlock.h b/vespalib/src/vespa/vespalib/util/rwlock.h deleted file mode 100644 index 8818291ae6c..00000000000 --- a/vespalib/src/vespa/vespalib/util/rwlock.h +++ /dev/null @@ -1,240 +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 <vespa/vespalib/util/sync.h> -#include <vespa/vespalib/util/guard.h> - -class RWLockTest; - -namespace vespalib { - -/** - * @brief An RWLock is a reader/writer lock. It can either be held by - * any number of readers or a single writer at any time. - * - * The RWLockReader and RWLockWriter classes are used to acquire and - * release reader and writer locks respectively. - * - * Writer locks have priority above reader locks to prevent - * starvation. - **/ -class RWLock -{ -private: - friend class ::RWLockTest; - friend class RWLockReader; - friend class RWLockWriter; - - int _givenLocks; - int _waitingReaders; - int _waitingWriters; - Monitor _monitor; - - void lockRead(); - void unlockRead(); - void lockWrite(); - void unlockWrite(); -public: - /** - * @brief Create a new RWLock - **/ - RWLock() - : _givenLocks(0), - _waitingReaders(0), - _waitingWriters(0), - _monitor() {} - /** - * @brief Create a new RWLock, ignoring the right hand side. - * - * It makes no sense to copy the state of an RWLock, but we want - * to allow copying objects that contain RWLock objects. - * - * @param rhs ignore this - **/ - RWLock(const RWLock &rhs) - : _givenLocks(0), - _waitingReaders(0), - _waitingWriters(0), - _monitor() { (void) rhs;} - /** - * @brief Assignment operator ignoring the right hand side. - * - * It makes no sense to assign the state of one RWLock to another, - * but we want to allow assigning objects that contain RWLock - * objects. - * - * @param rhs ignore this - **/ - RWLock &operator=(const RWLock &rhs) { - (void) rhs; - return *this; - } - - /** - * To get an instance of RWLockReader or RWLockWriter that isn't - * associated with a specific RWLock at initialization, you may - * construct them from this tag type. - **/ - struct InitiallyUnlockedGuard {}; -}; - -#ifndef IAM_DOXYGEN -class RWLockReaderHandover -{ -private: - friend class RWLockReader; - RWLock *_lock; - RWLockReaderHandover(const RWLockReaderHandover &); - RWLockReaderHandover &operator=(const RWLockReaderHandover &); - RWLockReaderHandover(RWLock *m) : _lock(m) {} -public: -}; - -class RWLockWriterHandover -{ -private: - friend class RWLockWriter; - RWLock *_lock; - RWLockWriterHandover(const RWLockWriterHandover &); - RWLockWriterHandover &operator=(const RWLockWriterHandover &); - RWLockWriterHandover(RWLock *m) : _lock(m) {} -public: -}; -#endif - - -/** - * @brief An RWLockReader holds a reader lock on an RWLock. - * - * The lock is acquired in the constructor and released in the - * destructor. - * - * RWLockReader has destructive copy (like unique_ptr). Assigning from - * or copying a RWLockReader has the semantic of transferring the lock - * from one object to the other. Note that assigning from or copying - * a RWLockReader that does not have a lock will result in an assert. - **/ -class RWLockReader -{ -private: - RWLock * _lock; - RWLock * stealLock(); - void cleanup() { if (_lock != nullptr) { _lock->unlockRead(); } } -public: - - /** - * @brief Obtain reader lock. - * - * This will block until a reader lock can be acquired. - * - * @param lock the underlying RWLock object - **/ - RWLockReader(RWLock &lock) : _lock(&lock) { _lock->lockRead(); } - - /** - * @brief Construct initially unlocked guard. - * @param tag (unused) marker argument - **/ - RWLockReader(const RWLock::InitiallyUnlockedGuard &tag) : _lock(nullptr) { (void)tag; } - - /** - * @brief Steal the lock from the given RWLockReader - * - * @param rhs steal the lock from this one - **/ - RWLockReader(RWLockReader &rhs) : _lock(rhs.stealLock()) {} - - /** - * @brief Steal the lock from the given RWLockReader - * - * @param rhs steal the lock from this one - **/ - RWLockReader &operator=(RWLockReader & rhs) { - if (this != & rhs) { - cleanup(); - _lock = rhs.stealLock(); - } - return *this; - } - - /** - * @brief Release the lock obtained in the constructor - **/ - ~RWLockReader() { cleanup(); } - -#ifndef IAM_DOXYGEN - RWLockReader(const RWLockReaderHandover &rhs) : _lock(rhs._lock) {} - operator RWLockReaderHandover() { return RWLockReaderHandover(stealLock()); } -#endif -}; - - -/** - * @brief An RWLockWriter holds a writer lock on an RWLock. - * - * The lock is acquired in the constructor and released in the - * destructor. - * - * RWLockWriter has destructive copy (like unique_ptr). Assigning from - * or copying a RWLockWriter has the semantic of transferring the lock - * from one object to the other, and assignment is similar. Note that - * assigning from or copying a RWLockWriter that does not have a lock - * will result in an assert. - **/ -class RWLockWriter -{ -private: - RWLock * _lock; - RWLock * stealLock(); - void cleanup() { if (_lock != nullptr) { _lock->unlockWrite(); } } -public: - - /** - * @brief Obtain writer lock. - * - * This will block until a writer lock can be acquired. - * - * @param lock the underlying RWLock object - **/ - RWLockWriter(RWLock &lock) : _lock(&lock) { _lock->lockWrite(); } - - /** - * @brief Construct initially unlocked guard. - * @param tag (unused) marker argument - **/ - RWLockWriter(const RWLock::InitiallyUnlockedGuard &tag) : _lock(nullptr) { (void)tag; } - - /** - * @brief Steal the lock from the given RWLockWriter - * - * @param rhs steal the lock from this one - **/ - RWLockWriter(RWLockWriter &rhs) : _lock(rhs.stealLock()) {} - - /** - * @brief Steal the lock from the given RWLockWriter - * - * @param rhs steal the lock from this one - **/ - RWLockWriter &operator=(RWLockWriter & rhs) { - if (this != & rhs) { - cleanup(); - _lock = rhs.stealLock(); - } - return *this; - } - - /** - * @brief Release the lock obtained in the constructor - **/ - ~RWLockWriter() { cleanup(); } - -#ifndef IAM_DOXYGEN - RWLockWriter(const RWLockWriterHandover &rhs) : _lock(rhs._lock) {} - operator RWLockWriterHandover() { return RWLockWriterHandover(stealLock()); } -#endif -}; - -} // namespace vespalib - diff --git a/vespalib/src/vespa/vespalib/util/simple_thread_bundle.cpp b/vespalib/src/vespa/vespalib/util/simple_thread_bundle.cpp index 886003a2ab6..e0d78c5d1b7 100644 --- a/vespalib/src/vespa/vespalib/util/simple_thread_bundle.cpp +++ b/vespalib/src/vespa/vespalib/util/simple_thread_bundle.cpp @@ -69,7 +69,7 @@ SimpleThreadBundle::UP SimpleThreadBundle::Pool::obtain() { { - LockGuard guard(_lock); + std::lock_guard guard(_lock); if (!_bundles.empty()) { SimpleThreadBundle::UP ret(_bundles.back()); _bundles.pop_back(); @@ -82,7 +82,7 @@ SimpleThreadBundle::Pool::obtain() void SimpleThreadBundle::Pool::release(SimpleThreadBundle::UP bundle) { - LockGuard guard(_lock); + std::lock_guard guard(_lock); _bundles.push_back(bundle.get()); bundle.release(); } diff --git a/vespalib/src/vespa/vespalib/util/simple_thread_bundle.h b/vespalib/src/vespa/vespalib/util/simple_thread_bundle.h index dbf9f7025b6..135fc2d7562 100644 --- a/vespalib/src/vespa/vespalib/util/simple_thread_bundle.h +++ b/vespalib/src/vespa/vespalib/util/simple_thread_bundle.h @@ -2,7 +2,6 @@ #pragma once -#include "sync.h" #include "count_down_latch.h" #include "thread.h" #include "runnable.h" @@ -94,8 +93,8 @@ public: class Pool { private: - Lock _lock; - size_t _bundleSize; + std::mutex _lock; + size_t _bundleSize; std::vector<SimpleThreadBundle*> _bundles; public: diff --git a/vespalib/src/vespa/vespalib/util/sync.cpp b/vespalib/src/vespa/vespalib/util/sync.cpp index 3819b2b3369..ac55f12c341 100644 --- a/vespalib/src/vespa/vespalib/util/sync.cpp +++ b/vespalib/src/vespa/vespalib/util/sync.cpp @@ -19,47 +19,10 @@ Monitor::Monitor() noexcept Monitor::Monitor(Monitor &&rhs) noexcept = default; Monitor::~Monitor() = default; - -TryLock::TryLock(const Lock &lock) - : _guard(*lock._mutex, std::try_to_lock), - _cond(nullptr) -{} - -TryLock::TryLock(const Monitor &mon) - : _guard(*mon._mutex, std::try_to_lock), - _cond(_guard ? mon._cond.get() : nullptr) -{} - -TryLock::TryLock(TryLock &&rhs) noexcept - : _guard(std::move(rhs._guard)), - _cond(rhs._cond) -{ - rhs._cond = nullptr; -} - -TryLock::~TryLock() = default; - -bool -TryLock::hasLock() const { - return static_cast<bool>(_guard); -} - -void -TryLock::unlock() { - if (_guard) { - _guard.unlock(); - _cond = nullptr; - } -} - LockGuard::LockGuard() : _guard() {} LockGuard::LockGuard(LockGuard &&rhs) noexcept : _guard(std::move(rhs._guard)) { } LockGuard::LockGuard(const Lock &lock) : _guard(*lock._mutex) { } -LockGuard::LockGuard(TryLock &&tlock) : _guard(std::move(tlock._guard)) -{ - tlock._cond = nullptr; -} LockGuard & LockGuard::operator=(LockGuard &&rhs) noexcept{ @@ -93,16 +56,6 @@ MonitorGuard::MonitorGuard(const Monitor &monitor) : _guard(*monitor._mutex), _cond(monitor._cond.get()) { } -MonitorGuard::MonitorGuard(TryLock &&tlock) - : _guard(), - _cond(nullptr) -{ - if (tlock._guard && tlock._cond != nullptr) { - _guard = std::move(tlock._guard); - _cond = tlock._cond; - tlock._cond = nullptr; - } -} MonitorGuard & MonitorGuard::operator=(MonitorGuard &&rhs) noexcept { diff --git a/vespalib/src/vespa/vespalib/util/sync.h b/vespalib/src/vespa/vespalib/util/sync.h index b1227ce658e..3207206a753 100644 --- a/vespalib/src/vespa/vespalib/util/sync.h +++ b/vespalib/src/vespa/vespalib/util/sync.h @@ -70,89 +70,6 @@ public: /** - * @brief A TryLock object is used to try to obtain the lock on a Lock - * or a Monitor without blocking. - * - * A TryLock will typically fail to obatin the lock if someone else - * already has it. In that case, the TryLock object has no further - * use. - * - * If the TryLock managed to acquire the lock, it can be passed over - * to a LockGuard or MonitorGuard object. If the lock is not passed - * on, the TryLock object will release it when it goes out of scope. - * - * Note that passing the lock obtained from a Lock to a MonitorGuard - * is illegal. Also note that if the TryLock fails to aquire the lock, - * it cannot be passed on. Trying to do so will result in an assert. - * - * copy/assignment of a TryLock is illegal. - * - * <pre> - * Example: - * - * Lock lock; - * TryLock tl(lock); - * if (tl.hasLock()) { - * LockGuard guard(tl) - * ... do stuff - * } // the lock is released as 'guard' goes out of scope - * </pre> - **/ -class TryLock -{ -private: - friend class LockGuard; - friend class MonitorGuard; - - std::unique_lock<std::mutex> _guard; - std::condition_variable *_cond; - -public: - /** - * @brief Try to obtain the lock represented by the given Lock object - * - * @param lock the lock to obtain - **/ - TryLock(const Lock &lock); - - /** - * @brief Try to lock the given Monitor - * - * @param mon the monitor to lock - **/ - TryLock(const Monitor &mon); - - TryLock(TryLock &&rhs) noexcept; - - /** - * @brief Release the lock held by this object, if any - **/ - ~TryLock(); - - TryLock(const TryLock &) = delete; - TryLock &operator=(const TryLock &) = delete; - - TryLock &operator=(TryLock &&rhs) noexcept; - - /** - * @brief Check whether this object holds a lock - * - * @return true if this object holds a lock - **/ - bool hasLock() const; - /** - * @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 A LockGuard holds the lock on either a Lock or a Monitor. * * LockGuards are typically created on the stack to hold a lock within @@ -191,17 +108,6 @@ public: **/ LockGuard(const Lock &lock); - /** - * @brief Create a LockGuard from a TryLock. - * - * The TryLock may have been created from either a Lock or a - * Monitor, but it must have managed to acquire the lock. The lock - * will be handed over from the TryLock to the new object. - * - * @param tlock take the lock from this one - **/ - LockGuard(TryLock &&tlock); - LockGuard &operator=(LockGuard &&rhs) noexcept; /** @@ -267,16 +173,6 @@ public: * @param monitor take the lock on it **/ MonitorGuard(const Monitor &monitor); - /** - * @brief Create a MonitorGuard from a TryLock. - * - * The TryLock must have been created from a Monitor, and it must - * have managed to acquire the lock. The lock will be handed over - * from the TryLock to the new object. - * - * @param tlock take the lock from this one - **/ - MonitorGuard(TryLock &&tlock); MonitorGuard &operator=(MonitorGuard &&rhs) noexcept; |