зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1083101 - Back 5 patches out due to windows build issues, CLOSED TREE.
This commit is contained in:
Родитель
b5f0ba8f9a
Коммит
5c994c47a4
|
@ -1,80 +0,0 @@
|
|||
/* -*- 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/. */
|
||||
|
||||
#ifndef MOZILLA_GFX_CRITICALSECTION_H_
|
||||
#define MOZILLA_GFX_CRITICALSECTION_H_
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <pthread.h>
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
class CriticalSection {
|
||||
public:
|
||||
CriticalSection() { ::InitializeCriticalSection(&mCriticalSection); }
|
||||
|
||||
~CriticalSection() { ::DeleteCriticalSection(&mCriticalSection); }
|
||||
|
||||
void Enter() { ::EnterCriticalSection(&mCriticalSection); }
|
||||
|
||||
void Leave() { ::LeaveCriticalSection(&mCriticalSection); }
|
||||
|
||||
protected:
|
||||
CRITICAL_SECTION mCriticalSection;
|
||||
};
|
||||
|
||||
#else
|
||||
// posix
|
||||
|
||||
class PosixCondvar;
|
||||
class CriticalSection {
|
||||
public:
|
||||
CriticalSection() {
|
||||
DebugOnly<int> err = pthread_mutex_init(&mMutex, nullptr);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
~CriticalSection() {
|
||||
DebugOnly<int> err = pthread_mutex_destroy(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
void Enter() {
|
||||
DebugOnly<int> err = pthread_mutex_lock(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
void Leave() {
|
||||
DebugOnly<int> err = pthread_mutex_unlock(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
protected:
|
||||
pthread_mutex_t mMutex;
|
||||
friend class PosixCondVar;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
/// RAII helper.
|
||||
struct CriticalSectionAutoEnter {
|
||||
explicit CriticalSectionAutoEnter(CriticalSection* aSection) : mSection(aSection) { mSection->Enter(); }
|
||||
~CriticalSectionAutoEnter() { mSection->Leave(); }
|
||||
protected:
|
||||
CriticalSection* mSection;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -23,7 +23,7 @@ bool JobScheduler::Init(uint32_t aNumThreads, uint32_t aNumQueues)
|
|||
}
|
||||
|
||||
for (uint32_t i = 0; i < aNumThreads; ++i) {
|
||||
sSingleton->mWorkerThreads.push_back(WorkerThread::Create(sSingleton->mDrawingQueues[i%aNumQueues]));
|
||||
sSingleton->mWorkerThreads.push_back(new WorkerThread(sSingleton->mDrawingQueues[i%aNumQueues]));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -84,8 +84,7 @@ JobScheduler::GetQueueForJob(Job* aJob)
|
|||
}
|
||||
|
||||
Job::Job(SyncObject* aStart, SyncObject* aCompletion, WorkerThread* aThread)
|
||||
: mNextWaitingJob(nullptr)
|
||||
, mStartSync(aStart)
|
||||
: mStartSync(aStart)
|
||||
, mCompletionSync(aCompletion)
|
||||
, mPinToThread(aThread)
|
||||
{
|
||||
|
@ -125,7 +124,6 @@ SetEventJob::~SetEventJob()
|
|||
|
||||
SyncObject::SyncObject(uint32_t aNumPrerequisites)
|
||||
: mSignals(aNumPrerequisites)
|
||||
, mFirstWaitingJob(nullptr)
|
||||
#ifdef DEBUG
|
||||
, mNumPrerequisites(aNumPrerequisites)
|
||||
, mAddedPrerequisites(0)
|
||||
|
@ -134,7 +132,7 @@ SyncObject::SyncObject(uint32_t aNumPrerequisites)
|
|||
|
||||
SyncObject::~SyncObject()
|
||||
{
|
||||
MOZ_ASSERT(mFirstWaitingJob == nullptr);
|
||||
MOZ_ASSERT(mWaitingJobs.size() == 0);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -186,41 +184,28 @@ SyncObject::Signal()
|
|||
void
|
||||
SyncObject::AddWaitingJob(Job* aJob)
|
||||
{
|
||||
// Push (using atomics) the task into the list of waiting tasks.
|
||||
for (;;) {
|
||||
Job* first = mFirstWaitingJob;
|
||||
aJob->mNextWaitingJob = first;
|
||||
if (mFirstWaitingJob.compareExchange(first, aJob)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
MutexAutoLock lock(&mMutex);
|
||||
mWaitingJobs.push_back(aJob);
|
||||
}
|
||||
|
||||
void SyncObject::SubmitWaitingJobs()
|
||||
{
|
||||
// Scheduling the tasks can cause code that modifies <this>'s reference
|
||||
// count to run concurrently, and cause the caller of this function to
|
||||
// be owned by another thread. We need to make sure the reference count
|
||||
// does not reach 0 on another thread before the end of this method, so
|
||||
// hold a strong ref to prevent that!
|
||||
RefPtr<SyncObject> kungFuDeathGrip(this);
|
||||
std::vector<Job*> tasksToSubmit;
|
||||
{
|
||||
// Scheduling the tasks can cause code that modifies <this>'s reference
|
||||
// count to run concurrently, and cause the caller of this function to
|
||||
// be owned by another thread. We need to make sure the reference count
|
||||
// does not reach 0 on another thread before mWaitingJobs.clear(), so
|
||||
// hold a strong ref to prevent that!
|
||||
RefPtr<SyncObject> kungFuDeathGrip(this);
|
||||
|
||||
// First atomically swap mFirstWaitingJob and waitingJobs...
|
||||
Job* waitingJobs = nullptr;
|
||||
for (;;) {
|
||||
waitingJobs = mFirstWaitingJob;
|
||||
if (mFirstWaitingJob.compareExchange(waitingJobs, nullptr)) {
|
||||
break;
|
||||
}
|
||||
MutexAutoLock lock(&mMutex);
|
||||
tasksToSubmit = Move(mWaitingJobs);
|
||||
mWaitingJobs.clear();
|
||||
}
|
||||
|
||||
// ... and submit all of the waiting tasks in waitingJob now that they belong
|
||||
// to this thread.
|
||||
while (waitingJobs) {
|
||||
Job* next = waitingJobs->mNextWaitingJob;
|
||||
waitingJobs->mNextWaitingJob = nullptr;
|
||||
JobScheduler::GetQueueForJob(waitingJobs)->SubmitJob(waitingJobs);
|
||||
waitingJobs = next;
|
||||
for (Job* task : tasksToSubmit) {
|
||||
JobScheduler::GetQueueForJob(task)->SubmitJob(task);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,33 +232,5 @@ SyncObject::AddSubsequent(Job* aJob)
|
|||
{
|
||||
}
|
||||
|
||||
WorkerThread::WorkerThread(MultiThreadedJobQueue* aJobQueue)
|
||||
: mQueue(aJobQueue)
|
||||
{
|
||||
aJobQueue->RegisterThread();
|
||||
}
|
||||
|
||||
void
|
||||
WorkerThread::Run()
|
||||
{
|
||||
SetName("gfx worker");
|
||||
|
||||
for (;;) {
|
||||
Job* commands = nullptr;
|
||||
if (!mQueue->WaitForJob(commands)) {
|
||||
mQueue->UnregisterThread();
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatus status = JobScheduler::ProcessJob(commands);
|
||||
|
||||
if (status == JobStatus::Error) {
|
||||
// Don't try to handle errors for now, but that's open to discussions.
|
||||
// I expect errors to be mostly OOM issues.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} //namespace
|
||||
} //namespace
|
||||
|
|
|
@ -15,14 +15,11 @@
|
|||
#include "mozilla/gfx/JobScheduler_posix.h"
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class MultiThreadedJobQueue;
|
||||
class SyncObject;
|
||||
class WorkerThread;
|
||||
|
||||
class JobScheduler {
|
||||
public:
|
||||
|
@ -109,16 +106,9 @@ public:
|
|||
WorkerThread* GetWorkerThread() { return mPinToThread; }
|
||||
|
||||
protected:
|
||||
// An intrusive linked list of tasks waiting for a sync object to enter the
|
||||
// signaled state. When the task is not waiting for a sync object, mNextWaitingJob
|
||||
// should be null. This is only accessed from the thread that owns the task.
|
||||
Job* mNextWaitingJob;
|
||||
|
||||
RefPtr<SyncObject> mStartSync;
|
||||
RefPtr<SyncObject> mCompletionSync;
|
||||
WorkerThread* mPinToThread;
|
||||
|
||||
friend class SyncObject;
|
||||
};
|
||||
|
||||
class EventObject;
|
||||
|
@ -212,8 +202,9 @@ private:
|
|||
|
||||
void SubmitWaitingJobs();
|
||||
|
||||
std::vector<Job*> mWaitingJobs;
|
||||
Mutex mMutex; // for concurrent access to mWaintingJobs
|
||||
Atomic<int32_t> mSignals;
|
||||
Atomic<Job*> mFirstWaitingJob;
|
||||
|
||||
#ifdef DEBUG
|
||||
uint32_t mNumPrerequisites;
|
||||
|
@ -224,26 +215,16 @@ private:
|
|||
friend class JobScheduler;
|
||||
};
|
||||
|
||||
/// Base class for worker threads.
|
||||
class WorkerThread
|
||||
{
|
||||
public:
|
||||
static WorkerThread* Create(MultiThreadedJobQueue* aJobQueue);
|
||||
|
||||
virtual ~WorkerThread() {}
|
||||
|
||||
void Run();
|
||||
|
||||
MultiThreadedJobQueue* GetJobQueue() { return mQueue; }
|
||||
|
||||
/// RAII helper.
|
||||
struct MutexAutoLock {
|
||||
MutexAutoLock(Mutex* aMutex) : mMutex(aMutex) { mMutex->Lock(); }
|
||||
~MutexAutoLock() { mMutex->Unlock(); }
|
||||
protected:
|
||||
explicit WorkerThread(MultiThreadedJobQueue* aJobQueue);
|
||||
|
||||
virtual void SetName(const char* aName) {}
|
||||
|
||||
MultiThreadedJobQueue* mQueue;
|
||||
Mutex* mMutex;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -11,52 +11,6 @@ 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* aName) override
|
||||
{
|
||||
// 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)
|
||||
|
@ -154,6 +108,62 @@ MultiThreadedJobQueue::UnregisterThread()
|
|||
}
|
||||
}
|
||||
|
||||
void* ThreadCallback(void* threadData)
|
||||
{
|
||||
WorkerThread* thread = (WorkerThread*)threadData;
|
||||
thread->Run();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WorkerThread::WorkerThread(MultiThreadedJobQueue* aJobQueue)
|
||||
: mQueue(aJobQueue)
|
||||
{
|
||||
aJobQueue->RegisterThread();
|
||||
pthread_create(&mThread, nullptr, ThreadCallback, this);
|
||||
}
|
||||
|
||||
WorkerThread::~WorkerThread()
|
||||
{
|
||||
pthread_join(mThread, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
WorkerThread::SetName(const char* aName)
|
||||
{
|
||||
// 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
|
||||
}
|
||||
|
||||
void
|
||||
WorkerThread::Run()
|
||||
{
|
||||
SetName("gfx worker");
|
||||
|
||||
for (;;) {
|
||||
Job* commands = nullptr;
|
||||
if (!mQueue->WaitForJob(commands)) {
|
||||
mQueue->UnregisterThread();
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatus status = JobScheduler::ProcessJob(commands);
|
||||
|
||||
if (status == JobStatus::Error) {
|
||||
// Don't try to handle errors for now, but that's open to discussions.
|
||||
// I expect errors to be mostly OOM issues.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EventObject::EventObject()
|
||||
: mIsSet(false)
|
||||
{}
|
||||
|
|
|
@ -16,17 +16,39 @@
|
|||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/gfx/CriticalSection.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class Job;
|
||||
class PosixCondVar;
|
||||
class WorkerThread;
|
||||
|
||||
typedef mozilla::gfx::CriticalSection Mutex;
|
||||
typedef mozilla::gfx::CriticalSectionAutoEnter MutexAutoLock;
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex() {
|
||||
DebugOnly<int> err = pthread_mutex_init(&mMutex, nullptr);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
~Mutex() {
|
||||
DebugOnly<int> err = pthread_mutex_destroy(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
void Lock() {
|
||||
DebugOnly<int> err = pthread_mutex_lock(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
void Unlock() {
|
||||
DebugOnly<int> err = pthread_mutex_unlock(&mMutex);
|
||||
MOZ_ASSERT(!err);
|
||||
}
|
||||
|
||||
protected:
|
||||
pthread_mutex_t mMutex;
|
||||
friend class PosixCondVar;
|
||||
};
|
||||
|
||||
// posix platforms only!
|
||||
class PosixCondVar {
|
||||
|
@ -109,6 +131,27 @@ protected:
|
|||
friend class WorkerThread;
|
||||
};
|
||||
|
||||
/// Worker thread that continuously dequeues Jobs from a MultiThreadedJobQueue
|
||||
/// and process them.
|
||||
///
|
||||
/// The public interface of this class must remain identical to its equivalent
|
||||
/// in JobScheduler_win32.h
|
||||
class WorkerThread {
|
||||
public:
|
||||
explicit WorkerThread(MultiThreadedJobQueue* aJobQueue);
|
||||
|
||||
~WorkerThread();
|
||||
|
||||
void Run();
|
||||
|
||||
MultiThreadedJobQueue* GetJobQueue() { return mQueue; }
|
||||
protected:
|
||||
void SetName(const char* name);
|
||||
|
||||
MultiThreadedJobQueue* mQueue;
|
||||
pthread_t mThread;
|
||||
};
|
||||
|
||||
/// An object that a thread can synchronously wait on.
|
||||
/// Usually set by a SetEventJob.
|
||||
class EventObject : public external::AtomicRefCounted<EventObject>
|
||||
|
|
|
@ -1,143 +0,0 @@
|
|||
/* -*- 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 {
|
||||
|
||||
DWORD __stdcall ThreadCallback(void* threadData);
|
||||
|
||||
class WorkerThreadWin32 : public WorkerThread {
|
||||
public:
|
||||
explicit WorkerThreadWin32(MultiThreadedJobQueue* aJobQueue)
|
||||
: WorkerThread(aJobQueue)
|
||||
{
|
||||
mThread = ::CreateThread(nullptr, 0, ThreadCallback, static_cast<WorkerThread*>(this), 0, nullptr);
|
||||
}
|
||||
|
||||
~WorkerThreadWin32()
|
||||
{
|
||||
::WaitForSingleObject(mThread, INFINITE);
|
||||
::CloseHandle(mThread);
|
||||
}
|
||||
|
||||
protected:
|
||||
HANDLE mThread;
|
||||
};
|
||||
|
||||
DWORD __stdcall ThreadCallback(void* threadData)
|
||||
{
|
||||
WorkerThread* thread = static_cast<WorkerThread*>(threadData);
|
||||
thread->Run();
|
||||
return 0;
|
||||
}
|
||||
|
||||
WorkerThread*
|
||||
WorkerThread::Create(MultiThreadedJobQueue* aJobQueue)
|
||||
{
|
||||
return new WorkerThreadWin32(aJobQueue);
|
||||
}
|
||||
|
||||
bool
|
||||
MultiThreadedJobQueue::PopJob(Job*& aOutJob, AccessType aAccess)
|
||||
{
|
||||
for (;;) {
|
||||
while (aAccess == BLOCKING && mJobs.empty()) {
|
||||
{
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
if (mShuttingDown) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
HANDLE handles[] = { mAvailableEvent, mShutdownEvent };
|
||||
::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
|
||||
}
|
||||
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
|
||||
if (mShuttingDown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mJobs.empty()) {
|
||||
if (aAccess == NON_BLOCKING) {
|
||||
return false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
Job* task = mJobs.front();
|
||||
MOZ_ASSERT(task);
|
||||
|
||||
mJobs.pop_front();
|
||||
|
||||
if (mJobs.empty()) {
|
||||
::ResetEvent(mAvailableEvent);
|
||||
}
|
||||
|
||||
aOutJob = task;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MultiThreadedJobQueue::SubmitJob(Job* aJob)
|
||||
{
|
||||
MOZ_ASSERT(aJob);
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
mJobs.push_back(aJob);
|
||||
::SetEvent(mAvailableEvent);
|
||||
}
|
||||
|
||||
void
|
||||
MultiThreadedJobQueue::ShutDown()
|
||||
{
|
||||
{
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
mShuttingDown = true;
|
||||
}
|
||||
while (mThreadsCount) {
|
||||
::SetEvent(mAvailableEvent);
|
||||
::WaitForSingleObject(mShutdownEvent, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
MultiThreadedJobQueue::NumJobs()
|
||||
{
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
return mJobs.size();
|
||||
}
|
||||
|
||||
bool
|
||||
MultiThreadedJobQueue::IsEmpty()
|
||||
{
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
return mJobs.empty();
|
||||
}
|
||||
|
||||
void
|
||||
MultiThreadedJobQueue::RegisterThread()
|
||||
{
|
||||
mThreadsCount += 1;
|
||||
}
|
||||
|
||||
void
|
||||
MultiThreadedJobQueue::UnregisterThread()
|
||||
{
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
mThreadsCount -= 1;
|
||||
if (mThreadsCount == 0) {
|
||||
::SetEvent(mShutdownEvent);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
|
@ -10,10 +10,6 @@
|
|||
#define NOT_IMPLEMENTED MOZ_CRASH("Not implemented")
|
||||
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/gfx/CriticalSection.h"
|
||||
#include <windows.h>
|
||||
#include <synchapi.h>
|
||||
#include <list>
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
@ -21,6 +17,14 @@ namespace gfx {
|
|||
class WorkerThread;
|
||||
class Job;
|
||||
|
||||
class Mutex {
|
||||
public:
|
||||
Mutex() { NOT_IMPLEMENTED; }
|
||||
~Mutex() { NOT_IMPLEMENTED; }
|
||||
void Lock() { NOT_IMPLEMENTED; }
|
||||
void Unlock() { NOT_IMPLEMENTED; }
|
||||
};
|
||||
|
||||
// The public interface of this class must remain identical to its equivalent
|
||||
// in JobScheduler_posix.h
|
||||
class MultiThreadedJobQueue {
|
||||
|
@ -30,43 +34,14 @@ public:
|
|||
NON_BLOCKING
|
||||
};
|
||||
|
||||
MultiThreadedJobQueue()
|
||||
: mThreadsCount(0)
|
||||
, mShuttingDown(false)
|
||||
{
|
||||
mAvailableEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
mShutdownEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
|
||||
}
|
||||
|
||||
~MultiThreadedJobQueue()
|
||||
{
|
||||
::CloseHandle(mAvailableEvent);
|
||||
::CloseHandle(mShutdownEvent);
|
||||
}
|
||||
|
||||
bool WaitForJob(Job*& aOutJob) { return PopJob(aOutJob, BLOCKING); }
|
||||
|
||||
bool PopJob(Job*& aOutJob, AccessType aAccess);
|
||||
|
||||
void SubmitJob(Job* aJob);
|
||||
|
||||
void ShutDown();
|
||||
|
||||
size_t NumJobs();
|
||||
|
||||
bool IsEmpty();
|
||||
|
||||
void RegisterThread();
|
||||
|
||||
void UnregisterThread();
|
||||
|
||||
protected:
|
||||
std::list<Job*> mJobs;
|
||||
CriticalSection mSection;
|
||||
HANDLE mAvailableEvent;
|
||||
HANDLE mShutdownEvent;
|
||||
int32_t mThreadsCount;
|
||||
bool mShuttingDown;
|
||||
bool WaitForJob(Job*& aOutCommands) { NOT_IMPLEMENTED; }
|
||||
bool PopJob(Job*& aOutCommands, AccessType aAccess) { NOT_IMPLEMENTED; }
|
||||
void SubmitJob(Job* aCommands) { NOT_IMPLEMENTED; }
|
||||
void ShutDown() { NOT_IMPLEMENTED; }
|
||||
size_t NumJobs() { NOT_IMPLEMENTED; }
|
||||
bool IsEmpty() { NOT_IMPLEMENTED; }
|
||||
void RegisterThread() { NOT_IMPLEMENTED; }
|
||||
void UnregisterThread() { NOT_IMPLEMENTED; }
|
||||
|
||||
friend class WorkerThread;
|
||||
};
|
||||
|
@ -79,18 +54,19 @@ class EventObject : public external::AtomicRefCounted<EventObject>
|
|||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(EventObject)
|
||||
|
||||
EventObject() { mEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); }
|
||||
EventObject() { NOT_IMPLEMENTED; }
|
||||
~EventObject() { NOT_IMPLEMENTED; }
|
||||
void Wait() { NOT_IMPLEMENTED; }
|
||||
bool Peak() { NOT_IMPLEMENTED; }
|
||||
void Set() { NOT_IMPLEMENTED; }
|
||||
};
|
||||
|
||||
~EventObject() { ::CloseHandle(mEvent); }
|
||||
|
||||
void Wait() { ::WaitForSingleObject(mEvent, INFINITE); }
|
||||
|
||||
bool Peak() { return ::WaitForSingleObject(mEvent, 0) == WAIT_OBJECT_0; }
|
||||
|
||||
void Set() { ::SetEvent(mEvent); }
|
||||
protected:
|
||||
// TODO: it's expensive to create events so we should try to reuse them
|
||||
HANDLE mEvent;
|
||||
// The public interface of this class must remain identical to its equivalent
|
||||
// in JobScheduler_posix.h
|
||||
class WorkerThread {
|
||||
public:
|
||||
explicit WorkerThread(MultiThreadedJobQueue* aJobQueue) { NOT_IMPLEMENTED; }
|
||||
void Run();
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -20,7 +20,6 @@ EXPORTS.mozilla.gfx += [
|
|||
'Blur.h',
|
||||
'BorrowedContext.h',
|
||||
'Coord.h',
|
||||
'CriticalSection.h',
|
||||
'DataSurfaceHelpers.h',
|
||||
'DrawTargetTiled.h',
|
||||
'Filters.h',
|
||||
|
@ -65,7 +64,6 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
|||
'DrawTargetD2D1.cpp',
|
||||
'ExtendInputEffectD2D1.cpp',
|
||||
'FilterNodeD2D1.cpp',
|
||||
'JobScheduler_win32.cpp',
|
||||
'PathD2D.cpp',
|
||||
'RadialGradientEffectD2D1.cpp',
|
||||
'ScaledFontDWrite.cpp',
|
||||
|
|
|
@ -3,16 +3,15 @@
|
|||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "mozilla/gfx/JobScheduler.h"
|
||||
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -25,17 +24,15 @@ using namespace mozilla;
|
|||
// things more apparent (if any).
|
||||
void MaybeYieldThread()
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (rand() % 5 == 0) {
|
||||
sched_yield();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Used by the TestCommand to check that tasks are processed in the right order.
|
||||
struct SanityChecker {
|
||||
std::vector<uint64_t> mAdvancements;
|
||||
mozilla::gfx::CriticalSection mSection;
|
||||
mozilla::gfx::Mutex mMutex;
|
||||
|
||||
explicit SanityChecker(uint64_t aNumCmdBuffers)
|
||||
{
|
||||
|
@ -47,7 +44,7 @@ struct SanityChecker {
|
|||
virtual void Check(uint64_t aJobId, uint64_t aCmdId)
|
||||
{
|
||||
MaybeYieldThread();
|
||||
CriticalSectionAutoEnter lock(&mSection);
|
||||
MutexAutoLock lock(&mMutex);
|
||||
ASSERT_EQ(mAdvancements[aJobId], aCmdId-1);
|
||||
mAdvancements[aJobId] = aCmdId;
|
||||
}
|
||||
|
@ -245,3 +242,5 @@ TEST(Moz2D, JobScheduler_Chain) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче