From 69603709edfcbdca829a275f2acc553fb898fdde Mon Sep 17 00:00:00 2001 From: Francois Ferrand Date: Mon, 11 Sep 2017 12:09:40 +0200 Subject: THRIFT-4327: add API to efficiently remove a single timer Client: C++ This closes #1353 --- lib/cpp/test/concurrency/Tests.cpp | 16 ++++++- lib/cpp/test/concurrency/TimerManagerTests.h | 68 ++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) (limited to 'lib/cpp/test') diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp index d09d438d6..df5099d8b 100644 --- a/lib/cpp/test/concurrency/Tests.cpp +++ b/lib/cpp/test/concurrency/Tests.cpp @@ -45,7 +45,7 @@ int main(int argc, char** argv) { // lower the scale of every test WEIGHT = 1; } - + bool runAll = args[0].compare("all") == 0; if (runAll || args[0].compare("thread-factory") == 0) { @@ -137,6 +137,20 @@ int main(int argc, char** argv) { std::cerr << "\t\tTimerManager tests FAILED" << std::endl; return 1; } + + std::cout << "\t\tTimerManager test03" << std::endl; + + if (!timerManagerTests.test03()) { + std::cerr << "\t\tTimerManager tests FAILED" << std::endl; + return 1; + } + + std::cout << "\t\tTimerManager test04" << std::endl; + + if (!timerManagerTests.test04()) { + std::cerr << "\t\tTimerManager tests FAILED" << std::endl; + return 1; + } } if (runAll || args[0].compare("thread-manager") == 0) { diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h index 80d373bef..3779b0d18 100644 --- a/lib/cpp/test/concurrency/TimerManagerTests.h +++ b/lib/cpp/test/concurrency/TimerManagerTests.h @@ -192,6 +192,74 @@ public: return true; } + /** + * This test creates two tasks, removes the first one then waits for the second one. It then + * verifies that the timer manager properly clean up itself and the remaining orphaned timeout + * task when the manager goes out of scope and its destructor is called. + */ + bool test03(int64_t timeout = 1000LL) { + TimerManager timerManager; + timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.start(); + assert(timerManager.state() == TimerManager::STARTED); + + Synchronized s(_monitor); + + // Setup the two tasks + shared_ptr taskToRemove + = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 2)); + TimerManager::Timer timer = timerManager.add(taskToRemove, taskToRemove->_timeout); + + shared_ptr task + = shared_ptr(new TimerManagerTests::Task(_monitor, timeout)); + timerManager.add(task, task->_timeout); + + // Remove one task and wait until the other has completed + timerManager.remove(timer); + _monitor.wait(timeout * 2); + + assert(!taskToRemove->_done); + assert(task->_done); + + // Verify behavior when removing the removed task + try { + timerManager.remove(timer); + assert(0 == "ERROR: This remove should send a NoSuchTaskException exception."); + } catch (NoSuchTaskException&) { + } + + return true; + } + + /** + * This test creates one tasks, and tries to remove it after it has expired. + */ + bool test04(int64_t timeout = 1000LL) { + TimerManager timerManager; + timerManager.threadFactory(shared_ptr(new PlatformThreadFactory())); + timerManager.start(); + assert(timerManager.state() == TimerManager::STARTED); + + Synchronized s(_monitor); + + // Setup the task + shared_ptr task + = shared_ptr(new TimerManagerTests::Task(_monitor, timeout / 10)); + TimerManager::Timer timer = timerManager.add(task, task->_timeout); + + // Wait until the task has completed + _monitor.wait(timeout); + + // Verify behavior when removing the expired task + try { + timerManager.remove(timer); + assert(0 == "ERROR: This remove should send a NoSuchTaskException exception."); + } catch (NoSuchTaskException&) { + } + + return true; + } + friend class TestTask; Monitor _monitor; -- cgit v1.2.1