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 #ifndef __THREAD__ 35 #define __THREAD__ 36 37 38 #include <Debug.h> 39 #include <Looper.h> 40 #include <OS.h> 41 42 #include "ObjectList.h" 43 #include "FunctionObject.h" 44 45 46 namespace BPrivate { 47 48 class MessengerAutoLocker { 49 // move this into AutoLock.h 50 public: 51 MessengerAutoLocker(BMessenger* messenger) 52 : fMessenger(messenger), 53 fHasLock(messenger->LockTarget()) 54 {} 55 56 ~MessengerAutoLocker() 57 { 58 Unlock(); 59 } 60 61 bool operator!() const 62 { 63 return !fHasLock; 64 } 65 66 bool IsLocked() const 67 { 68 return fHasLock; 69 } 70 71 void Unlock() 72 { 73 if (fHasLock) { 74 BLooper* looper; 75 fMessenger->Target(&looper); 76 if (looper) 77 looper->Unlock(); 78 fHasLock = false; 79 } 80 } 81 82 private: 83 BMessenger* fMessenger; 84 bool fHasLock; 85 }; 86 87 88 class SimpleThread { 89 // this should only be used as a base class, 90 // subclass needs to add proper locking mechanism 91 public: 92 SimpleThread(int32 priority = B_LOW_PRIORITY, const char* name = 0); 93 virtual ~SimpleThread(); 94 95 void Go(); 96 97 private: 98 static status_t RunBinder(void*); 99 virtual void Run() = 0; 100 101 protected: 102 thread_id fScanThread; 103 int32 fPriority; 104 const char* fName; 105 }; 106 107 108 class Thread : private SimpleThread { 109 public: 110 static void Launch(FunctionObject* functor, 111 int32 priority = B_LOW_PRIORITY, const char* name = 0); 112 113 private: 114 Thread(FunctionObject*, int32 priority, const char* name); 115 ~Thread(); 116 virtual void Run(); 117 118 FunctionObject* fFunctor; 119 }; 120 121 122 class ThreadSequence : private SimpleThread { 123 public: 124 static void Launch(BObjectList<FunctionObject>*, bool async = true, 125 int32 priority = B_LOW_PRIORITY); 126 127 private: 128 ThreadSequence(BObjectList<FunctionObject>*, int32 priority); 129 ~ThreadSequence(); 130 131 virtual void Run(); 132 static void Run(BObjectList<FunctionObject>*list); 133 134 BObjectList<FunctionObject>* fFunctorList; 135 }; 136 137 138 // would use SingleParamFunctionObjectWithResult, except mwcc won't handle this 139 template <class Param1> 140 class SingleParamFunctionObjectWorkaround : public 141 FunctionObjectWithResult<status_t> { 142 public: 143 SingleParamFunctionObjectWorkaround( 144 status_t (*function)(Param1), Param1 param1) 145 : fFunction(function), 146 fParam1(param1) 147 { 148 } 149 150 virtual void operator()() 151 { (fFunction)(fParam1); } 152 153 virtual ulong Size() const { return sizeof(*this); } 154 155 private: 156 status_t (*fFunction)(Param1); 157 Param1 fParam1; 158 }; 159 160 161 template <class T> 162 class SimpleMemberFunctionObjectWorkaround : public 163 FunctionObjectWithResult<status_t> { 164 public: 165 SimpleMemberFunctionObjectWorkaround(status_t (T::*function)(), T* onThis) 166 : fFunction(function), 167 fOnThis(onThis) 168 { 169 } 170 171 virtual void operator()() 172 { (fOnThis->*fFunction)(); } 173 174 virtual ulong Size() const { return sizeof(*this); } 175 176 private: 177 status_t (T::*fFunction)(); 178 T fOnThis; 179 }; 180 181 182 template <class Param1, class Param2> 183 class TwoParamFunctionObjectWorkaround : public 184 FunctionObjectWithResult<status_t> { 185 public: 186 TwoParamFunctionObjectWorkaround(status_t (*callThis)(Param1, Param2), 187 Param1 param1, Param2 param2) 188 : function(callThis), 189 fParam1(param1), 190 fParam2(param2) 191 { 192 } 193 194 virtual void operator()() 195 { (function)(fParam1, fParam2); } 196 197 virtual uint32 Size() const { return sizeof(*this); } 198 199 private: 200 status_t (*function)(Param1, Param2); 201 Param1 fParam1; 202 Param2 fParam2; 203 }; 204 205 206 template <class Param1, class Param2, class Param3> 207 class ThreeParamFunctionObjectWorkaround : public 208 FunctionObjectWithResult<status_t> { 209 public: 210 ThreeParamFunctionObjectWorkaround( 211 status_t (*callThis)(Param1, Param2, Param3), 212 Param1 param1, Param2 param2, Param3 param3) 213 : function(callThis), 214 fParam1(param1), 215 fParam2(param2), 216 fParam3(param3) 217 { 218 } 219 220 virtual void operator()() 221 { (function)(fParam1, fParam2, fParam3); } 222 223 virtual uint32 Size() const { return sizeof(*this); } 224 225 private: 226 status_t (*function)(Param1, Param2, Param3); 227 Param1 fParam1; 228 Param2 fParam2; 229 Param3 fParam3; 230 }; 231 232 233 template <class Param1, class Param2, class Param3, class Param4> 234 class FourParamFunctionObjectWorkaround : public 235 FunctionObjectWithResult<status_t> { 236 public: 237 FourParamFunctionObjectWorkaround( 238 status_t (*callThis)(Param1, Param2, Param3, Param4), 239 Param1 param1, Param2 param2, Param3 param3, Param4 param4) 240 : function(callThis), 241 fParam1(param1), 242 fParam2(param2), 243 fParam3(param3), 244 fParam4(param4) 245 { 246 } 247 248 virtual void operator()() 249 { (function)(fParam1, fParam2, fParam3, fParam4); } 250 251 virtual uint32 Size() const { return sizeof(*this); } 252 253 private: 254 status_t (*function)(Param1, Param2, Param3, Param4); 255 Param1 fParam1; 256 Param2 fParam2; 257 Param3 fParam3; 258 Param4 fParam4; 259 }; 260 261 262 template<class Param1> 263 void 264 LaunchInNewThread(const char* name, int32 priority, status_t (*func)(Param1), 265 Param1 p1) 266 { 267 Thread::Launch(new SingleParamFunctionObjectWorkaround<Param1>(func, p1), 268 priority, name); 269 } 270 271 272 template<class T> 273 void 274 LaunchInNewThread(const char* name, int32 priority, status_t (T::*function)(), 275 T* onThis) 276 { 277 Thread::Launch(new SimpleMemberFunctionObjectWorkaround<T>(function, 278 onThis), priority, name); 279 } 280 281 282 template<class Param1, class Param2> 283 void 284 LaunchInNewThread(const char* name, int32 priority, 285 status_t (*func)(Param1, Param2), 286 Param1 p1, Param2 p2) 287 { 288 Thread::Launch(new 289 TwoParamFunctionObjectWorkaround<Param1, Param2>(func, p1, p2), 290 priority, name); 291 } 292 293 294 template<class Param1, class Param2, class Param3> 295 void 296 LaunchInNewThread(const char* name, int32 priority, 297 status_t (*func)(Param1, Param2, Param3), 298 Param1 p1, Param2 p2, Param3 p3) 299 { 300 Thread::Launch(new ThreeParamFunctionObjectWorkaround<Param1, Param2, 301 Param3>(func, p1, p2, p3), priority, name); 302 } 303 304 305 template<class Param1, class Param2, class Param3, class Param4> 306 void 307 LaunchInNewThread(const char* name, int32 priority, 308 status_t (*func)(Param1, Param2, Param3, Param4), 309 Param1 p1, Param2 p2, Param3 p3, Param4 p4) 310 { 311 Thread::Launch(new FourParamFunctionObjectWorkaround<Param1, Param2, 312 Param3, Param4>(func, p1, p2, p3, p4), priority, name); 313 } 314 315 316 template<class View> 317 class MouseDownThread { 318 public: 319 static void TrackMouse(View* view, void (View::*)(BPoint), 320 void (View::*)(BPoint, uint32) = 0, 321 bigtime_t pressingPeriod = 100000); 322 323 protected: 324 MouseDownThread(View* view, void (View::*)(BPoint), 325 void (View::*)(BPoint, uint32), bigtime_t pressingPeriod); 326 327 virtual ~MouseDownThread(); 328 329 void Go(); 330 virtual void Track(); 331 332 static status_t TrackBinder(void*); 333 334 private: 335 BMessenger fOwner; 336 void (View::*fDonePressing)(BPoint); 337 void (View::*fPressing)(BPoint, uint32); 338 bigtime_t fPressingPeriod; 339 volatile thread_id fThreadID; 340 }; 341 342 343 template<class View> 344 void 345 MouseDownThread<View>::TrackMouse(View* view, 346 void(View::*donePressing)(BPoint), 347 void(View::*pressing)(BPoint, uint32), bigtime_t pressingPeriod) 348 { 349 (new MouseDownThread(view, donePressing, pressing, pressingPeriod))->Go(); 350 } 351 352 353 template<class View> 354 MouseDownThread<View>::MouseDownThread(View* view, 355 void (View::*donePressing)(BPoint), 356 void (View::*pressing)(BPoint, uint32), bigtime_t pressingPeriod) 357 : fOwner(view, view->Window()), 358 fDonePressing(donePressing), 359 fPressing(pressing), 360 fPressingPeriod(pressingPeriod) 361 { 362 } 363 364 365 template<class View> 366 MouseDownThread<View>::~MouseDownThread() 367 { 368 } 369 370 371 template<class View> 372 void 373 MouseDownThread<View>::Go() 374 { 375 fThreadID = spawn_thread(&MouseDownThread::TrackBinder, 376 "MouseTrackingThread", B_NORMAL_PRIORITY, this); 377 378 if (fThreadID <= 0 || resume_thread(fThreadID) != B_OK) 379 // didn't start, don't leak self 380 delete this; 381 } 382 383 384 template<class View> 385 status_t 386 MouseDownThread<View>::TrackBinder(void* castToThis) 387 { 388 MouseDownThread* self = static_cast<MouseDownThread*>(castToThis); 389 self->Track(); 390 // dead at this point 391 return B_OK; 392 } 393 394 395 template<class View> 396 void 397 MouseDownThread<View>::Track() 398 { 399 for (;;) { 400 MessengerAutoLocker lock(&fOwner); 401 if (!lock) 402 break; 403 404 BLooper* looper; 405 View* view = dynamic_cast<View*>(fOwner.Target(&looper)); 406 if (!view) 407 break; 408 409 uint32 buttons; 410 BPoint location; 411 view->GetMouse(&location, &buttons, false); 412 if (!buttons) { 413 (view->*fDonePressing)(location); 414 break; 415 } 416 if (fPressing) 417 (view->*fPressing)(location, buttons); 418 419 lock.Unlock(); 420 snooze(fPressingPeriod); 421 } 422 423 delete this; 424 } 425 426 427 } // namespace BPrivate 428 429 using namespace BPrivate; 430 431 #endif // __THREAD__ 432