diff options
Diffstat (limited to 'gfx/2d/JobScheduler_posix.cpp')
-rw-r--r-- | gfx/2d/JobScheduler_posix.cpp | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/gfx/2d/JobScheduler_posix.cpp b/gfx/2d/JobScheduler_posix.cpp new file mode 100644 index 000000000..e41388f21 --- /dev/null +++ b/gfx/2d/JobScheduler_posix.cpp @@ -0,0 +1,194 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "JobScheduler.h" +#include "mozilla/gfx/Logging.h" + +using namespace std; + +namespace mozilla { +namespace gfx { + +void* ThreadCallback(void* threadData); + +class WorkerThreadPosix : public WorkerThread { +public: + explicit WorkerThreadPosix(MultiThreadedJobQueue* aJobQueue) + : WorkerThread(aJobQueue) + { + pthread_create(&mThread, nullptr, ThreadCallback, static_cast<WorkerThread*>(this)); + } + + ~WorkerThreadPosix() + { + pthread_join(mThread, nullptr); + } + + virtual void SetName(const char*) override + { +// XXX - temporarily disabled, see bug 1209039 +// +// // Call this from the thread itself because of Mac. +//#ifdef XP_MACOSX +// pthread_setname_np(aName); +//#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) +// pthread_set_name_np(mThread, aName); +//#elif defined(__NetBSD__) +// pthread_setname_np(mThread, "%s", (void*)aName); +//#else +// pthread_setname_np(mThread, aName); +//#endif + } + +protected: + pthread_t mThread; +}; + +void* ThreadCallback(void* threadData) +{ + WorkerThread* thread = static_cast<WorkerThread*>(threadData); + thread->Run(); + return nullptr; +} + +WorkerThread* +WorkerThread::Create(MultiThreadedJobQueue* aJobQueue) +{ + return new WorkerThreadPosix(aJobQueue); +} + +MultiThreadedJobQueue::MultiThreadedJobQueue() +: mThreadsCount(0) +, mShuttingDown(false) +{} + +MultiThreadedJobQueue::~MultiThreadedJobQueue() +{ + MOZ_ASSERT(mJobs.empty()); +} + +bool +MultiThreadedJobQueue::WaitForJob(Job*& aOutJob) +{ + return PopJob(aOutJob, BLOCKING); +} + +bool +MultiThreadedJobQueue::PopJob(Job*& aOutJobs, AccessType aAccess) +{ + for (;;) { + CriticalSectionAutoEnter lock(&mMutex); + + while (aAccess == BLOCKING && !mShuttingDown && mJobs.empty()) { + mAvailableCondvar.Wait(&mMutex); + } + + if (mShuttingDown) { + return false; + } + + if (mJobs.empty()) { + if (aAccess == NON_BLOCKING) { + return false; + } + continue; + } + + Job* task = mJobs.front(); + MOZ_ASSERT(task); + + mJobs.pop_front(); + + aOutJobs = task; + return true; + } +} + +void +MultiThreadedJobQueue::SubmitJob(Job* aJobs) +{ + MOZ_ASSERT(aJobs); + CriticalSectionAutoEnter lock(&mMutex); + mJobs.push_back(aJobs); + mAvailableCondvar.Broadcast(); +} + +size_t +MultiThreadedJobQueue::NumJobs() +{ + CriticalSectionAutoEnter lock(&mMutex); + return mJobs.size(); +} + +bool +MultiThreadedJobQueue::IsEmpty() +{ + CriticalSectionAutoEnter lock(&mMutex); + return mJobs.empty(); +} + +void +MultiThreadedJobQueue::ShutDown() +{ + CriticalSectionAutoEnter lock(&mMutex); + mShuttingDown = true; + while (mThreadsCount) { + mAvailableCondvar.Broadcast(); + mShutdownCondvar.Wait(&mMutex); + } +} + +void +MultiThreadedJobQueue::RegisterThread() +{ + mThreadsCount += 1; +} + +void +MultiThreadedJobQueue::UnregisterThread() +{ + CriticalSectionAutoEnter lock(&mMutex); + mThreadsCount -= 1; + if (mThreadsCount == 0) { + mShutdownCondvar.Broadcast(); + } +} + +EventObject::EventObject() +: mIsSet(false) +{} + +EventObject::~EventObject() +{} + +bool +EventObject::Peak() +{ + CriticalSectionAutoEnter lock(&mMutex); + return mIsSet; +} + +void +EventObject::Set() +{ + CriticalSectionAutoEnter lock(&mMutex); + if (!mIsSet) { + mIsSet = true; + mCond.Broadcast(); + } +} + +void +EventObject::Wait() +{ + CriticalSectionAutoEnter lock(&mMutex); + if (mIsSet) { + return; + } + mCond.Wait(&mMutex); +} + +} // namespce +} // namespce |