More bullet proofing of timer manager

facebook::thrift::concurrency::TimerManager::stop
	Added proper cleanup of unprocessed tasks and shutdown of dispatcher thread to stop

facebook::thrift::concurrency::TimerManager::~TimerManager
	Call stop if manager wasn't explicitly stopped

facebook::thrift::concurrency::test.TimerManagerTest
	Calculate error margin for timeout expiration and verify it's within bounds
	Verify manager stops properly when it goes out of scope
	


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664724 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/concurrency/test/TimerManagerTests.h b/lib/cpp/src/concurrency/test/TimerManagerTests.h
index 24f7964..f34f8b0 100644
--- a/lib/cpp/src/concurrency/test/TimerManagerTests.h
+++ b/lib/cpp/src/concurrency/test/TimerManagerTests.h
@@ -1,6 +1,7 @@
 #include <TimerManager.h>
 #include <PosixThreadFactory.h>
 #include <Monitor.h>
+#include <Util.h>
 
 #include <assert.h>
 #include <iostream>
@@ -20,12 +21,30 @@
 
   public:
     
-  Task(Monitor& monitor) : 
+  Task(Monitor& monitor, long long timeout) : 
+    _timeout(timeout),
+    _startTime(Util::currentTime()),
     _monitor(monitor),
+    _success(false),
     _done(false) {}
 
     void run() {
 
+      _endTime = Util::currentTime();
+
+      // Figure out error percentage
+
+      long long delta = _endTime - _startTime;
+
+
+      delta = delta > _timeout ?  delta - _timeout : _timeout - delta;
+
+      float error = delta / _timeout;
+
+      if(error < .10) {
+	_success = true;
+      }
+      
       std::cout << "\t\t\tHello World" << std::endl;
 
       _done = true;
@@ -34,37 +53,60 @@
 	_monitor.notifyAll();
       }
     }
-    
+
+
+    long long _timeout;
+    long long _startTime;
+    long long _endTime;
     Monitor& _monitor;
+    bool _success;
     bool _done;
   };
 
 public:
 
-  bool test00() {
+  /** This test creates two tasks and waits for the first to expire within 10% of the expected expiration time.  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. */
 
-    TimerManager* timerManager =  new TimerManager();
+  bool test00(long long timeout=1000LL) {
 
-    timerManager->threadFactory(new PosixThreadFactory());
+    TimerManagerTests::Task* orphanTask = new TimerManagerTests::Task(_monitor, 10 * timeout);
 
-    timerManager->start();
+    {
 
-    assert(timerManager->state() == TimerManager::STARTED);
+      TimerManager timerManager;
+      
+      timerManager.threadFactory(new PosixThreadFactory());
+      
+      timerManager.start();
+      
+      assert(timerManager.state() == TimerManager::STARTED);
 
-    TimerManagerTests::Task* task = new TimerManagerTests::Task(_monitor);
+      TimerManagerTests::Task* task = new TimerManagerTests::Task(_monitor, timeout);
 
-    {Synchronized s(_monitor);
+      {Synchronized s(_monitor);
 
-      timerManager->add(task, 1000LL);
+	timerManager.add(orphanTask, 10 * timeout);
 
-      _monitor.wait();
+	timerManager.add(task, timeout);
+
+	_monitor.wait();
+      }
+
+      assert(task->_done);
+
+
+      std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl;
+
+      delete task;
     }
 
-    assert(task->_done);
+    // timerManager.stop(); This is where it happens via destructor
 
-    delete task;
+    assert(!orphanTask->_done);
 
-    std::cout << "\t\t\tSuccess!" << std::endl;
+    delete orphanTask;
 
     return true;
   }