llworkerthread.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * @file llworkerthread.h
  3. *
  4. * $LicenseInfo:firstyear=2004&license=viewergpl$
  5. *
  6. * Copyright (c) 2004-2009, Linden Research, Inc.
  7. *
  8. * Second Life Viewer Source Code
  9. * The source code in this file ("Source Code") is provided by Linden Lab
  10. * to you under the terms of the GNU General Public License, version 2.0
  11. * ("GPL"), unless you have obtained a separate licensing agreement
  12. * ("Other License"), formally executed by you and Linden Lab. Terms of
  13. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  14. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  15. *
  16. * There are special exceptions to the terms and conditions of the GPL as
  17. * it is applied to this Source Code. View the full text of the exception
  18. * in the file doc/FLOSS-exception.txt in this software distribution, or
  19. * online at
  20. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  21. *
  22. * By copying, modifying or distributing this software, you acknowledge
  23. * that you have read and understood your obligations described above,
  24. * and agree to abide by those obligations.
  25. *
  26. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  27. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  28. * COMPLETENESS OR PERFORMANCE.
  29. * $/LicenseInfo$
  30. */
  31. #ifndef LL_LLWORKERTHREAD_H
  32. #define LL_LLWORKERTHREAD_H
  33. #include <list>
  34. #include "llqueuedthread.h"
  35. class LLWorkerClass;
  36. // Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small
  37. // It is assumed that LLWorkerThreads are rarely created/destroyed.
  38. class LLWorkerThread : public LLQueuedThread
  39. {
  40. friend class LLWorkerClass;
  41. protected:
  42. LOG_CLASS(LLWorkerThread);
  43. public:
  44. class WorkRequest : public LLQueuedThread::QueuedRequest
  45. {
  46. protected:
  47. LOG_CLASS(LLWorkerThread::WorkRequest);
  48. protected:
  49. ~WorkRequest() override = default;; // use deleteRequest()
  50. public:
  51. WorkRequest(handle_t handle, U32 priority, LLWorkerClass* workerclass,
  52. S32 param);
  53. LL_INLINE S32 getParam() { return mParam; }
  54. LL_INLINE LLWorkerClass* getWorkerClass() { return mWorkerClass; }
  55. bool processRequest() override;
  56. void finishRequest(bool completed) override;
  57. void deleteRequest() override;
  58. private:
  59. LLWorkerClass* mWorkerClass;
  60. S32 mParam;
  61. };
  62. LLWorkerThread(const std::string& name);
  63. ~LLWorkerThread() override;
  64. size_t update() override;
  65. handle_t addWorkRequest(LLWorkerClass* workerclass, S32 param,
  66. U32 priority = PRIORITY_NORMAL);
  67. // Debug
  68. LL_INLINE S32 getNumDeletes() { return (S32)mDeleteList.size(); }
  69. protected:
  70. void clearDeleteList();
  71. private:
  72. void deleteWorker(LLWorkerClass* workerclass); // schedule for deletion
  73. private:
  74. typedef std::list<LLWorkerClass*> delete_list_t;
  75. delete_list_t mDeleteList;
  76. LLMutex mDeleteMutex;
  77. };
  78. // This is a base class which any class with worker functions should derive
  79. // from. Example usage:
  80. // LLMyWorkerClass* foo = new LLMyWorkerClass();
  81. // foo->fetchData(); // calls addWork()
  82. // while (true) // main loop
  83. // {
  84. // if (foo->hasData()) // calls checkWork()
  85. // {
  86. // foo->processData();
  87. // }
  88. // }
  89. //
  90. // WorkerClasses only have one set of work functions. If they need to do
  91. // multiple background tasks, use 'param' to switch amnong them. Only one
  92. // background task can be active at a time (per instance). I.e. don't call
  93. // addWork() if haveWork() returns true.
  94. class LLWorkerClass
  95. {
  96. friend class LLWorkerThread;
  97. friend class LLWorkerThread::WorkRequest;
  98. protected:
  99. LOG_CLASS(LLWorkerClass);
  100. public:
  101. typedef LLWorkerThread::handle_t handle_t;
  102. enum FLAGS
  103. {
  104. WCF_HAVE_WORK = 0x01,
  105. WCF_WORKING = 0x02,
  106. WCF_WORK_FINISHED = 0x10,
  107. WCF_WORK_ABORTED = 0x20,
  108. WCF_DELETE_REQUESTED = 0x40,
  109. WCF_ABORT_REQUESTED = 0x80
  110. };
  111. public:
  112. LLWorkerClass(LLWorkerThread* workerthread, const std::string& name);
  113. virtual ~LLWorkerClass();
  114. // Called from WorkRequest::processRequest() (WORKER THREAD), returns true
  115. // if done.
  116. virtual bool doWork(S32 param) = 0;
  117. // Called from finishRequest() (WORK THREAD) after completed or aborted
  118. LL_INLINE virtual void finishWork(S32 param, bool completed)
  119. {
  120. }
  121. // Returns true if safe to delete the worker, called from update() (WORK
  122. // THREAD), defaults to always OK
  123. LL_INLINE virtual bool deleteOK() { return true; }
  124. // Schedules deletion once aborted or completed
  125. void scheduleDelete();
  126. // haveWork() may still be true if aborted
  127. LL_INLINE bool haveWork() { return getFlags(WCF_HAVE_WORK); }
  128. LL_INLINE bool isWorking() { return getFlags(WCF_WORKING); }
  129. LL_INLINE bool wasAborted() { return getFlags(WCF_ABORT_REQUESTED); }
  130. // setPriority(): changes the priority of a request
  131. void setPriority(U32 priority);
  132. LL_INLINE U32 getPriority() { return mRequestPriority; }
  133. LL_INLINE const std::string& getName() const { return mWorkerClassName; }
  134. protected:
  135. // called from WORKER THREAD
  136. void setWorking(bool working);
  137. // Call from doWork only to avoid eating up cpu time. Returns true if work
  138. // has been aborted yields the current thread and calls
  139. // mWorkerThread->checkPause()
  140. bool yield();
  141. // Calls startWork, adds doWork() to queue
  142. void addWork(S32 param, U32 priority = LLWorkerThread::PRIORITY_NORMAL);
  143. // Requests that work be aborted
  144. void abortWork(bool autocomplete);
  145. // If doWork is complete or aborted, call endWork() and return true
  146. bool checkWork(bool aborting = false);
  147. private:
  148. LL_INLINE void setFlags(U32 flags) { mWorkFlags = mWorkFlags | flags; }
  149. LL_INLINE void clearFlags(U32 flags) { mWorkFlags = mWorkFlags & ~flags; }
  150. LL_INLINE U32 getFlags() { return mWorkFlags; }
  151. // Called from addWork() (MAIN THREAD)
  152. virtual void startWork(S32 param) = 0;
  153. // Called from doWork() (MAIN THREAD)
  154. virtual void endWork(S32 param, bool aborted) = 0;
  155. public:
  156. LL_INLINE bool getFlags(U32 flags) { return (mWorkFlags & flags) != 0; }
  157. protected:
  158. LLWorkerThread* mWorkerThread;
  159. std::string mWorkerClassName;
  160. handle_t mRequestHandle;
  161. U32 mRequestPriority; // Last priority set
  162. private:
  163. LLMutex mMutex;
  164. LLAtomicU32 mWorkFlags;
  165. };
  166. #endif // LL_LLWORKERTHREAD_H