1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 // 36 // Delayed Tasks, Periodic Delayed Tasks, Periodic Delayed Tasks with timeout, 37 // Run when idle tasks, accumulating delayed tasks 38 // 39 40 41 #ifndef __TASK_LOOP__ 42 #define __TASK_LOOP__ 43 44 #include <Locker.h> 45 46 #include "FunctionObject.h" 47 #include "ObjectList.h" 48 49 namespace BPrivate { 50 51 // Task flavors 52 53 class DelayedTask { 54 public: 55 DelayedTask(bigtime_t delay); 56 virtual ~DelayedTask(); 57 58 virtual bool RunIfNeeded(bigtime_t currentTime) = 0; 59 // returns true if done and should not be called again 60 61 bigtime_t RunAfterTime() const; 62 63 protected: 64 bigtime_t fRunAfter; 65 }; 66 67 class OneShotDelayedTask : public DelayedTask { 68 // called once after a specified delay 69 public: 70 OneShotDelayedTask(FunctionObject *functor, bigtime_t delay); 71 virtual ~OneShotDelayedTask(); 72 73 virtual bool RunIfNeeded(bigtime_t currentTime); 74 75 protected: 76 FunctionObject *fFunctor; 77 }; 78 79 class PeriodicDelayedTask : public DelayedTask { 80 // called periodically till functor return true 81 public: 82 PeriodicDelayedTask(FunctionObjectWithResult<bool> *functor, 83 bigtime_t initialDelay, bigtime_t period); 84 virtual ~PeriodicDelayedTask(); 85 86 virtual bool RunIfNeeded(bigtime_t currentTime); 87 88 protected: 89 bigtime_t fPeriod; 90 FunctionObjectWithResult<bool> *fFunctor; 91 }; 92 93 class PeriodicDelayedTaskWithTimeout : public PeriodicDelayedTask { 94 // called periodically till functor returns true or till time out 95 public: 96 PeriodicDelayedTaskWithTimeout(FunctionObjectWithResult<bool> *functor, 97 bigtime_t initialDelay, bigtime_t period, bigtime_t timeout); 98 99 virtual bool RunIfNeeded(bigtime_t currentTime); 100 101 protected: 102 bigtime_t fTimeoutAfter; 103 }; 104 105 class RunWhenIdleTask : public PeriodicDelayedTask { 106 // after initial delay starts periodically calling functor if system is idle 107 // until functor returns true 108 public: 109 RunWhenIdleTask(FunctionObjectWithResult<bool> *functor, bigtime_t initialDelay, 110 bigtime_t idleFor, bigtime_t heartBeat); 111 virtual ~RunWhenIdleTask(); 112 113 virtual bool RunIfNeeded(bigtime_t currentTime); 114 115 protected: 116 void ResetIdleTimer(bigtime_t currentTime); 117 bool IdleTimerExpired(bigtime_t currentTime); 118 bool StillIdle(bigtime_t currentTime); 119 bool IsIdle(bigtime_t currentTime, float taskOverhead); 120 121 bigtime_t fIdleFor; 122 123 enum State { 124 kInitialDelay, 125 kInitialIdleWait, 126 kInIdleState 127 }; 128 129 State fState; 130 bigtime_t fActivityLevelStart; 131 bigtime_t fActivityLevel; 132 bigtime_t fLastCPUTooBusyTime; 133 134 private: 135 typedef PeriodicDelayedTask _inherited; 136 }; 137 138 class AccumulatingFunctionObject : public FunctionObject { 139 // This class is used for clumping up function objects that 140 // can be done as a single object. For instance the mime 141 // notification mechanism sends out multiple notifications on 142 // a single change and we need to accumulate the resulting 143 // icon update into a single one 144 public: 145 virtual bool CanAccumulate(const AccumulatingFunctionObject *) const = 0; 146 virtual void Accumulate(AccumulatingFunctionObject *) = 0; 147 }; 148 149 150 // task loop is a separate thread that hosts tasks that keep getting called 151 // periodically; if a task returns true, it is done - it gets removed from 152 // the list and deleted 153 class TaskLoop { 154 public: 155 TaskLoop(bigtime_t heartBeat = 10000); 156 virtual ~TaskLoop(); 157 158 void RunLater(DelayedTask *); 159 void RunLater(FunctionObject *functor, bigtime_t delay); 160 // execute a function object after a delay 161 162 void RunLater(FunctionObjectWithResult<bool> *functor, bigtime_t delay, 163 bigtime_t period); 164 // periodically execute function object after initial delay until function 165 // object returns true 166 167 void RunLater(FunctionObjectWithResult<bool> *functor, bigtime_t delay, 168 bigtime_t period, bigtime_t timeout); 169 // periodically execute function object after initial delay until function 170 // object returns true or timeout is reached 171 172 void AccumulatedRunLater(AccumulatingFunctionObject *functor, bigtime_t delay, 173 bigtime_t maxAccumulatingTime = 0, int32 maxAccumulateCount = 0); 174 // will search the delayed task loop for other accumulating functors 175 // and will accumulate with them, else will create a new delayed task 176 // the task will no longer accumulate if past the <maxAccumulatingTime> delay 177 // unless <maxAccumulatingTime> is zero 178 // no more than <maxAccumulateCount> will get accumulated, unless 179 // <maxAccumulateCount> is zero 180 181 void RunWhenIdle(FunctionObjectWithResult<bool> *functor, bigtime_t initialDelay, 182 bigtime_t idleTime, bigtime_t heartBeat = 1000000); 183 // after initialDelay starts looking for a slot when the system is 184 // idle for at least idleTime 185 186 protected: 187 void AddTask(DelayedTask *); 188 void RemoveTask(DelayedTask *); 189 190 bool Pulse(); 191 // return true if quitting 192 bigtime_t LatestRunTime() const; 193 194 virtual bool KeepPulsingWhenEmpty() const = 0; 195 virtual void StartPulsingIfNeeded() = 0; 196 197 BLocker fLock; 198 BObjectList<DelayedTask> fTaskList; 199 bigtime_t fHeartBeat; 200 }; 201 202 class StandAloneTaskLoop : public TaskLoop { 203 // this task loop can work on it's own, just instantiate it 204 // and use it; It has to start it's own thread 205 public: 206 StandAloneTaskLoop(bool keepThread, bigtime_t heartBeat = 400000); 207 ~StandAloneTaskLoop(); 208 209 protected: 210 void AddTask(DelayedTask *); 211 212 private: 213 static status_t RunBinder(void *); 214 void Run(); 215 216 virtual bool KeepPulsingWhenEmpty() const; 217 virtual void StartPulsingIfNeeded(); 218 219 volatile bool fNeedToQuit; 220 volatile thread_id fScanThread; 221 bool fKeepThread; 222 223 typedef TaskLoop _inherited; 224 }; 225 226 class PiggybackTaskLoop : public TaskLoop { 227 // this TaskLoop needs periodic calls from a viewable's Pulse 228 // or some similar pulsing mechanism 229 // it does not have to need it's own thread, instead it uses an existing 230 // thread of a looper, etc. 231 public: 232 PiggybackTaskLoop(bigtime_t heartBeat = 100000); 233 ~PiggybackTaskLoop(); 234 virtual void PulseMe(); 235 private: 236 virtual bool KeepPulsingWhenEmpty() const; 237 virtual void StartPulsingIfNeeded(); 238 239 bigtime_t fNextHeartBeatTime; 240 bool fPulseMe; 241 }; 242 243 244 inline bigtime_t 245 DelayedTask::RunAfterTime() const 246 { 247 return fRunAfter; 248 } 249 250 } // namespace BPrivate 251 252 using namespace BPrivate; 253 254 #endif 255