| // Copyright (c) 2006- Facebook | 
 | // Distributed under the Thrift Software License | 
 | // | 
 | // See accompanying file LICENSE or visit the Thrift site at: | 
 | // http://developers.facebook.com/thrift/ | 
 |  | 
 | #include <concurrency/TimerManager.h> | 
 | #include <concurrency/PosixThreadFactory.h> | 
 | #include <concurrency/Monitor.h> | 
 | #include <concurrency/Util.h> | 
 |  | 
 | #include <assert.h> | 
 | #include <iostream> | 
 |  | 
 | namespace apache { namespace thrift { namespace concurrency { namespace test { | 
 |  | 
 | using namespace apache::thrift::concurrency; | 
 |  | 
 | /** | 
 |  * ThreadManagerTests class | 
 |  * | 
 |  * @author marc | 
 |  * @version $Id:$ | 
 |  */ | 
 | class TimerManagerTests { | 
 |  | 
 |  public: | 
 |  | 
 |   static const double ERROR; | 
 |  | 
 |   class Task: public Runnable { | 
 |    public: | 
 |  | 
 |     Task(Monitor& monitor, int64_t timeout) : | 
 |       _timeout(timeout), | 
 |       _startTime(Util::currentTime()), | 
 |       _monitor(monitor), | 
 |       _success(false), | 
 |       _done(false) {} | 
 |  | 
 |     ~Task() { std::cerr << this << std::endl; } | 
 |  | 
 |     void run() { | 
 |  | 
 |       _endTime = Util::currentTime(); | 
 |  | 
 |       // Figure out error percentage | 
 |  | 
 |       int64_t delta = _endTime - _startTime; | 
 |  | 
 |  | 
 |       delta = delta > _timeout ?  delta - _timeout : _timeout - delta; | 
 |  | 
 |       float error = delta / _timeout; | 
 |  | 
 |       if(error < ERROR) { | 
 |         _success = true; | 
 |       } | 
 |  | 
 |       _done = true; | 
 |  | 
 |       std::cout << "\t\t\tTimerManagerTests::Task[" << this << "] done" << std::endl; //debug | 
 |  | 
 |       {Synchronized s(_monitor); | 
 |         _monitor.notifyAll(); | 
 |       } | 
 |     } | 
 |  | 
 |     int64_t _timeout; | 
 |     int64_t _startTime; | 
 |     int64_t _endTime; | 
 |     Monitor& _monitor; | 
 |     bool _success; | 
 |     bool _done; | 
 |   }; | 
 |  | 
 |   /** | 
 |    * 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. | 
 |    */ | 
 |   bool test00(int64_t timeout=1000LL) { | 
 |  | 
 |     shared_ptr<TimerManagerTests::Task> orphanTask = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout)); | 
 |  | 
 |     { | 
 |  | 
 |       TimerManager timerManager; | 
 |  | 
 |       timerManager.threadFactory(shared_ptr<PosixThreadFactory>(new PosixThreadFactory())); | 
 |  | 
 |       timerManager.start(); | 
 |  | 
 |       assert(timerManager.state() == TimerManager::STARTED); | 
 |  | 
 |       shared_ptr<TimerManagerTests::Task> task = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, timeout)); | 
 |  | 
 |       { | 
 |         Synchronized s(_monitor); | 
 |  | 
 |         timerManager.add(orphanTask, 10 * timeout); | 
 |  | 
 |         timerManager.add(task, timeout); | 
 |  | 
 |         _monitor.wait(); | 
 |       } | 
 |  | 
 |       assert(task->_done); | 
 |  | 
 |  | 
 |       std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; | 
 |     } | 
 |  | 
 |     // timerManager.stop(); This is where it happens via destructor | 
 |  | 
 |     assert(!orphanTask->_done); | 
 |  | 
 |     return true; | 
 |   } | 
 |  | 
 |   friend class TestTask; | 
 |  | 
 |   Monitor _monitor; | 
 | }; | 
 |  | 
 | const double TimerManagerTests::ERROR = .20; | 
 |  | 
 | }}}} // apache::thrift::concurrency | 
 |  |