JobScheduler_posix.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2. * This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "JobScheduler.h"
  6. #include "mozilla/gfx/Logging.h"
  7. using namespace std;
  8. namespace mozilla {
  9. namespace gfx {
  10. void* ThreadCallback(void* threadData);
  11. class WorkerThreadPosix : public WorkerThread {
  12. public:
  13. explicit WorkerThreadPosix(MultiThreadedJobQueue* aJobQueue)
  14. : WorkerThread(aJobQueue)
  15. {
  16. pthread_create(&mThread, nullptr, ThreadCallback, static_cast<WorkerThread*>(this));
  17. }
  18. ~WorkerThreadPosix()
  19. {
  20. pthread_join(mThread, nullptr);
  21. }
  22. virtual void SetName(const char*) override
  23. {
  24. // XXX - temporarily disabled, see bug 1209039
  25. //
  26. // // Call this from the thread itself because of Mac.
  27. //#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
  28. // pthread_set_name_np(mThread, aName);
  29. //#elif defined(__NetBSD__)
  30. // pthread_setname_np(mThread, "%s", (void*)aName);
  31. //#else
  32. // pthread_setname_np(mThread, aName);
  33. //#endif
  34. }
  35. protected:
  36. pthread_t mThread;
  37. };
  38. void* ThreadCallback(void* threadData)
  39. {
  40. WorkerThread* thread = static_cast<WorkerThread*>(threadData);
  41. thread->Run();
  42. return nullptr;
  43. }
  44. WorkerThread*
  45. WorkerThread::Create(MultiThreadedJobQueue* aJobQueue)
  46. {
  47. return new WorkerThreadPosix(aJobQueue);
  48. }
  49. MultiThreadedJobQueue::MultiThreadedJobQueue()
  50. : mThreadsCount(0)
  51. , mShuttingDown(false)
  52. {}
  53. MultiThreadedJobQueue::~MultiThreadedJobQueue()
  54. {
  55. MOZ_ASSERT(mJobs.empty());
  56. }
  57. bool
  58. MultiThreadedJobQueue::WaitForJob(Job*& aOutJob)
  59. {
  60. return PopJob(aOutJob, BLOCKING);
  61. }
  62. bool
  63. MultiThreadedJobQueue::PopJob(Job*& aOutJobs, AccessType aAccess)
  64. {
  65. for (;;) {
  66. CriticalSectionAutoEnter lock(&mMutex);
  67. while (aAccess == BLOCKING && !mShuttingDown && mJobs.empty()) {
  68. mAvailableCondvar.Wait(&mMutex);
  69. }
  70. if (mShuttingDown) {
  71. return false;
  72. }
  73. if (mJobs.empty()) {
  74. if (aAccess == NON_BLOCKING) {
  75. return false;
  76. }
  77. continue;
  78. }
  79. Job* task = mJobs.front();
  80. MOZ_ASSERT(task);
  81. mJobs.pop_front();
  82. aOutJobs = task;
  83. return true;
  84. }
  85. }
  86. void
  87. MultiThreadedJobQueue::SubmitJob(Job* aJobs)
  88. {
  89. MOZ_ASSERT(aJobs);
  90. CriticalSectionAutoEnter lock(&mMutex);
  91. mJobs.push_back(aJobs);
  92. mAvailableCondvar.Broadcast();
  93. }
  94. size_t
  95. MultiThreadedJobQueue::NumJobs()
  96. {
  97. CriticalSectionAutoEnter lock(&mMutex);
  98. return mJobs.size();
  99. }
  100. bool
  101. MultiThreadedJobQueue::IsEmpty()
  102. {
  103. CriticalSectionAutoEnter lock(&mMutex);
  104. return mJobs.empty();
  105. }
  106. void
  107. MultiThreadedJobQueue::ShutDown()
  108. {
  109. CriticalSectionAutoEnter lock(&mMutex);
  110. mShuttingDown = true;
  111. while (mThreadsCount) {
  112. mAvailableCondvar.Broadcast();
  113. mShutdownCondvar.Wait(&mMutex);
  114. }
  115. }
  116. void
  117. MultiThreadedJobQueue::RegisterThread()
  118. {
  119. mThreadsCount += 1;
  120. }
  121. void
  122. MultiThreadedJobQueue::UnregisterThread()
  123. {
  124. CriticalSectionAutoEnter lock(&mMutex);
  125. mThreadsCount -= 1;
  126. if (mThreadsCount == 0) {
  127. mShutdownCondvar.Broadcast();
  128. }
  129. }
  130. EventObject::EventObject()
  131. : mIsSet(false)
  132. {}
  133. EventObject::~EventObject()
  134. {}
  135. bool
  136. EventObject::Peak()
  137. {
  138. CriticalSectionAutoEnter lock(&mMutex);
  139. return mIsSet;
  140. }
  141. void
  142. EventObject::Set()
  143. {
  144. CriticalSectionAutoEnter lock(&mMutex);
  145. if (!mIsSet) {
  146. mIsSet = true;
  147. mCond.Broadcast();
  148. }
  149. }
  150. void
  151. EventObject::Wait()
  152. {
  153. CriticalSectionAutoEnter lock(&mMutex);
  154. if (mIsSet) {
  155. return;
  156. }
  157. mCond.Wait(&mMutex);
  158. }
  159. } // namespce
  160. } // namespce