You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@thrift.apache.org by jk...@apache.org on 2017/09/09 03:24:27 UTC

thrift git commit: THRIFT-4292: Implement TimerManager::remove() Client: C++

Repository: thrift
Updated Branches:
  refs/heads/master 078281dcd -> cc2d558e2


THRIFT-4292: Implement TimerManager::remove()
Client: C++

This closes #1337


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/cc2d558e
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/cc2d558e
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/cc2d558e

Branch: refs/heads/master
Commit: cc2d558e2de1cae2bee2276bf83c39acc3b5987e
Parents: 078281d
Author: Francois Ferrand <th...@gmail.com>
Authored: Fri Aug 25 09:01:26 2017 +0200
Committer: James E. King, III <jk...@apache.org>
Committed: Fri Sep 8 20:23:50 2017 -0700

----------------------------------------------------------------------
 lib/cpp/src/thrift/concurrency/TimerManager.cpp | 16 ++++-
 lib/cpp/test/concurrency/Tests.cpp              | 14 +++++
 lib/cpp/test/concurrency/TimerManagerTests.h    | 66 ++++++++++++++++++++
 3 files changed, 95 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/cc2d558e/lib/cpp/src/thrift/concurrency/TimerManager.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/src/thrift/concurrency/TimerManager.cpp b/lib/cpp/src/thrift/concurrency/TimerManager.cpp
index b03ff42..9ae1f94 100644
--- a/lib/cpp/src/thrift/concurrency/TimerManager.cpp
+++ b/lib/cpp/src/thrift/concurrency/TimerManager.cpp
@@ -52,6 +52,8 @@ public:
     }
   }
 
+  bool operator==(const shared_ptr<Runnable> & runnable) const { return runnable_ == runnable; }
+
 private:
   shared_ptr<Runnable> runnable_;
   friend class TimerManager::Dispatcher;
@@ -290,11 +292,23 @@ void TimerManager::add(shared_ptr<Runnable> task, const struct timeval& value) {
 }
 
 void TimerManager::remove(shared_ptr<Runnable> task) {
-  (void)task;
   Synchronized s(monitor_);
   if (state_ != TimerManager::STARTED) {
     throw IllegalStateException();
   }
+  bool found = false;
+  for (task_iterator ix = taskMap_.begin(); ix != taskMap_.end();) {
+    if (*ix->second == task) {
+      found = true;
+      taskCount_--;
+      taskMap_.erase(ix++);
+    } else {
+      ++ix;
+    }
+  }
+  if (!found) {
+    throw NoSuchTaskException();
+  }
 }
 
 TimerManager::STATE TimerManager::state() const {

http://git-wip-us.apache.org/repos/asf/thrift/blob/cc2d558e/lib/cpp/test/concurrency/Tests.cpp
----------------------------------------------------------------------
diff --git a/lib/cpp/test/concurrency/Tests.cpp b/lib/cpp/test/concurrency/Tests.cpp
index f49bb9f..d09d438 100644
--- a/lib/cpp/test/concurrency/Tests.cpp
+++ b/lib/cpp/test/concurrency/Tests.cpp
@@ -123,6 +123,20 @@ int main(int argc, char** argv) {
       std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
       return 1;
     }
+
+    std::cout << "\t\tTimerManager test01" << std::endl;
+
+    if (!timerManagerTests.test01()) {
+      std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
+      return 1;
+    }
+
+    std::cout << "\t\tTimerManager test02" << std::endl;
+
+    if (!timerManagerTests.test02()) {
+      std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
+      return 1;
+    }
   }
 
   if (runAll || args[0].compare("thread-manager") == 0) {

http://git-wip-us.apache.org/repos/asf/thrift/blob/cc2d558e/lib/cpp/test/concurrency/TimerManagerTests.h
----------------------------------------------------------------------
diff --git a/lib/cpp/test/concurrency/TimerManagerTests.h b/lib/cpp/test/concurrency/TimerManagerTests.h
index 32d3935..80d373b 100644
--- a/lib/cpp/test/concurrency/TimerManagerTests.h
+++ b/lib/cpp/test/concurrency/TimerManagerTests.h
@@ -126,6 +126,72 @@ 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 test01(int64_t timeout = 1000LL) {
+    TimerManager timerManager;
+    timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
+    timerManager.start();
+    assert(timerManager.state() == TimerManager::STARTED);
+
+    Synchronized s(_monitor);
+
+    // Setup the two tasks
+    shared_ptr<TimerManagerTests::Task> taskToRemove
+      = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 2));
+    timerManager.add(taskToRemove, taskToRemove->_timeout);
+
+    shared_ptr<TimerManagerTests::Task> task
+      = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
+    timerManager.add(task, task->_timeout);
+
+    // Remove one task and wait until the other has completed
+    timerManager.remove(taskToRemove);
+    _monitor.wait(timeout * 2);
+
+    assert(!taskToRemove->_done);
+    assert(task->_done);
+
+    return true;
+  }
+
+  /**
+   * This test creates two tasks with the same callback and another one, then removes the two
+   * duplicated then waits for the last 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 test02(int64_t timeout = 1000LL) {
+    TimerManager timerManager;
+    timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
+    timerManager.start();
+    assert(timerManager.state() == TimerManager::STARTED);
+
+    Synchronized s(_monitor);
+
+    // Setup the one tasks and add it twice
+    shared_ptr<TimerManagerTests::Task> taskToRemove
+      = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout / 3));
+    timerManager.add(taskToRemove, taskToRemove->_timeout);
+    timerManager.add(taskToRemove, taskToRemove->_timeout * 2);
+
+    shared_ptr<TimerManagerTests::Task> task
+      = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout));
+    timerManager.add(task, task->_timeout);
+
+    // Remove the first task (e.g. two timers) and wait until the other has completed
+    timerManager.remove(taskToRemove);
+    _monitor.wait(timeout * 2);
+
+    assert(!taskToRemove->_done);
+    assert(task->_done);
+
+    return true;
+  }
+
   friend class TestTask;
 
   Monitor _monitor;