xref: /haiku/src/kits/tracker/TaskLoop.h (revision 2600324b57fa31cdea1627d584d314f2a579c4a8)
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