gecko-dev/gfx/2d/JobScheduler_posix.cpp

160 строки
3.7 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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));
}
virtual ~WorkerThreadPosix() { pthread_join(mThread, nullptr); }
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() = default;
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);
}
} // namespace gfx
} // namespace mozilla