| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Licensed to the Apache Software Foundation (ASF) under one | 
 | 3 |  * or more contributor license agreements. See the NOTICE file | 
 | 4 |  * distributed with this work for additional information | 
 | 5 |  * regarding copyright ownership. The ASF licenses this file | 
 | 6 |  * to you under the Apache License, Version 2.0 (the | 
 | 7 |  * "License"); you may not use this file except in compliance | 
 | 8 |  * with the License. You may obtain a copy of the License at | 
 | 9 |  * | 
 | 10 |  *   http://www.apache.org/licenses/LICENSE-2.0 | 
 | 11 |  * | 
 | 12 |  * Unless required by applicable law or agreed to in writing, | 
 | 13 |  * software distributed under the License is distributed on an | 
 | 14 |  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
 | 15 |  * KIND, either express or implied. See the License for the | 
 | 16 |  * specific language governing permissions and limitations | 
 | 17 |  * under the License. | 
 | 18 |  */ | 
| Mark Slee | 9f0c651 | 2007-02-28 23:58:26 +0000 | [diff] [blame] | 19 |  | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 20 | #include <concurrency/TimerManager.h> | 
| Roger Meier | 3faaedf | 2011-10-02 10:51:45 +0000 | [diff] [blame] | 21 | #include <concurrency/PlatformThreadFactory.h> | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 22 | #include <concurrency/Monitor.h> | 
 | 23 | #include <concurrency/Util.h> | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 24 |  | 
 | 25 | #include <assert.h> | 
 | 26 | #include <iostream> | 
 | 27 |  | 
| T Jake Luciani | b5e6221 | 2009-01-31 22:36:20 +0000 | [diff] [blame] | 28 | namespace apache { namespace thrift { namespace concurrency { namespace test { | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 29 |  | 
| T Jake Luciani | b5e6221 | 2009-01-31 22:36:20 +0000 | [diff] [blame] | 30 | using namespace apache::thrift::concurrency; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 31 |  | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 32 | /** | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 33 |  * ThreadManagerTests class | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 34 |  * | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 35 |  * @version $Id:$ | 
 | 36 |  */ | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 37 | class TimerManagerTests { | 
 | 38 |  | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 39 |  public: | 
 | 40 |  | 
 | 41 |   static const double ERROR; | 
 | 42 |  | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 43 |   class Task: public Runnable { | 
 | 44 |    public: | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 45 |  | 
 | 46 |     Task(Monitor& monitor, int64_t timeout) : | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 47 |       _timeout(timeout), | 
 | 48 |       _startTime(Util::currentTime()), | 
 | 49 |       _monitor(monitor), | 
 | 50 |       _success(false), | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 51 |       _done(false) {} | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 52 |  | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 53 |     ~Task() { std::cerr << this << std::endl; } | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 54 |  | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 55 |     void run() { | 
 | 56 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 57 |       _endTime = Util::currentTime(); | 
 | 58 |  | 
 | 59 |       // Figure out error percentage | 
 | 60 |  | 
| Mark Slee | 9b82d27 | 2007-05-23 05:16:07 +0000 | [diff] [blame] | 61 |       int64_t delta = _endTime - _startTime; | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 62 |  | 
 | 63 |  | 
 | 64 |       delta = delta > _timeout ?  delta - _timeout : _timeout - delta; | 
 | 65 |  | 
 | 66 |       float error = delta / _timeout; | 
 | 67 |  | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 68 |       if(error < ERROR) { | 
| David Reiss | 96d2388 | 2007-07-26 21:10:32 +0000 | [diff] [blame] | 69 |         _success = true; | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 70 |       } | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 71 |  | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 72 |       _done = true; | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 73 |  | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 74 |       std::cout << "\t\t\tTimerManagerTests::Task[" << this << "] done" << std::endl; //debug | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 75 |  | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 76 |       {Synchronized s(_monitor); | 
| David Reiss | 96d2388 | 2007-07-26 21:10:32 +0000 | [diff] [blame] | 77 |         _monitor.notifyAll(); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 78 |       } | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 79 |     } | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 80 |  | 
| Mark Slee | 9b82d27 | 2007-05-23 05:16:07 +0000 | [diff] [blame] | 81 |     int64_t _timeout; | 
 | 82 |     int64_t _startTime; | 
 | 83 |     int64_t _endTime; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 84 |     Monitor& _monitor; | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 85 |     bool _success; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 86 |     bool _done; | 
 | 87 |   }; | 
 | 88 |  | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 89 |   /** | 
 | 90 |    * This test creates two tasks and waits for the first to expire within 10% | 
 | 91 |    * of the expected expiration time. It then verifies that the timer manager | 
 | 92 |    * properly clean up itself and the remaining orphaned timeout task when the | 
 | 93 |    * manager goes out of scope and its destructor is called. | 
 | 94 |    */ | 
| Mark Slee | 9b82d27 | 2007-05-23 05:16:07 +0000 | [diff] [blame] | 95 |   bool test00(int64_t timeout=1000LL) { | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 96 |  | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 97 |     shared_ptr<TimerManagerTests::Task> orphanTask = shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout)); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 98 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 99 |     { | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 100 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 101 |       TimerManager timerManager; | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 102 |  | 
| Roger Meier | 3faaedf | 2011-10-02 10:51:45 +0000 | [diff] [blame] | 103 |       timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory())); | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 104 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 105 |       timerManager.start(); | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 106 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 107 |       assert(timerManager.state() == TimerManager::STARTED); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 108 |  | 
| David Reiss | 52687eb | 2009-06-04 00:32:57 +0000 | [diff] [blame] | 109 |       // Don't create task yet, because its constructor sets the expected completion time, and we | 
 | 110 |       // need to delay between inserting the two tasks into the run queue. | 
 | 111 |       shared_ptr<TimerManagerTests::Task> task; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 112 |  | 
| Mark Slee | f5f2be4 | 2006-09-05 21:05:31 +0000 | [diff] [blame] | 113 |       { | 
 | 114 |         Synchronized s(_monitor); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 115 |  | 
| David Reiss | 96d2388 | 2007-07-26 21:10:32 +0000 | [diff] [blame] | 116 |         timerManager.add(orphanTask, 10 * timeout); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 117 |  | 
| David Reiss | 52687eb | 2009-06-04 00:32:57 +0000 | [diff] [blame] | 118 |         try { | 
 | 119 |           // Wait for 1 second in order to give timerManager a chance to start sleeping in response | 
 | 120 |           // to adding orphanTask. We need to do this so we can verify that adding the second task | 
 | 121 |           // kicks the dispatcher out of the current wait and starts the new 1 second wait. | 
 | 122 |           _monitor.wait (1000); | 
 | 123 |           assert (0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem."); | 
 | 124 |         } catch (TimedOutException &ex) { | 
 | 125 |         } | 
 | 126 |  | 
 | 127 |         task.reset (new TimerManagerTests::Task(_monitor, timeout)); | 
 | 128 |  | 
| David Reiss | 96d2388 | 2007-07-26 21:10:32 +0000 | [diff] [blame] | 129 |         timerManager.add(task, timeout); | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 130 |  | 
| David Reiss | 96d2388 | 2007-07-26 21:10:32 +0000 | [diff] [blame] | 131 |         _monitor.wait(); | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 132 |       } | 
 | 133 |  | 
 | 134 |       assert(task->_done); | 
 | 135 |  | 
 | 136 |  | 
 | 137 |       std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 138 |     } | 
 | 139 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 140 |     // timerManager.stop(); This is where it happens via destructor | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 141 |  | 
| Marc Slemko | 9f27a4e | 2006-07-19 20:02:22 +0000 | [diff] [blame] | 142 |     assert(!orphanTask->_done); | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 143 |  | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 144 |     return true; | 
 | 145 |   } | 
 | 146 |  | 
 | 147 |   friend class TestTask; | 
 | 148 |  | 
 | 149 |   Monitor _monitor; | 
 | 150 | }; | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 151 |  | 
| Marc Slemko | 6f038a7 | 2006-08-03 18:58:09 +0000 | [diff] [blame] | 152 | const double TimerManagerTests::ERROR = .20; | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 153 |  | 
| T Jake Luciani | b5e6221 | 2009-01-31 22:36:20 +0000 | [diff] [blame] | 154 | }}}} // apache::thrift::concurrency | 
| Marc Slemko | 8a40a76 | 2006-07-19 17:46:50 +0000 | [diff] [blame] | 155 |  |