This source file includes following definitions.
- threadSetMutex
- workerThreads
- workerThreadCount
- m_shutdownEvent
- start
- workerThreadStart
- workerThread
- runEventLoop
- create
- performTask
- isCleanupTask
- create
- performTask
- isCleanupTask
- stop
- isCurrentThread
- performTask
- releaseFastMallocFreeMemoryInAllThreads
#include "config.h"
#include "core/workers/WorkerThread.h"
#include "bindings/v8/ScriptSourceCode.h"
#include "core/inspector/InspectorInstrumentation.h"
#include "core/workers/DedicatedWorkerGlobalScope.h"
#include "core/workers/WorkerClients.h"
#include "core/workers/WorkerReportingProxy.h"
#include "core/workers/WorkerThreadStartupData.h"
#include "platform/PlatformThreadData.h"
#include "platform/heap/ThreadState.h"
#include "platform/weborigin/KURL.h"
#include "public/platform/Platform.h"
#include "public/platform/WebWaitableEvent.h"
#include "public/platform/WebWorkerRunLoop.h"
#include "wtf/Noncopyable.h"
#include "wtf/text/WTFString.h"
#include <utility>
namespace WebCore {
static Mutex& threadSetMutex()
{
AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
return mutex;
}
static HashSet<WorkerThread*>& workerThreads()
{
DEFINE_STATIC_LOCAL(HashSet<WorkerThread*>, threads, ());
return threads;
}
unsigned WorkerThread::workerThreadCount()
{
MutexLocker lock(threadSetMutex());
return workerThreads().size();
}
WorkerThread::WorkerThread(WorkerLoaderProxy& workerLoaderProxy, WorkerReportingProxy& workerReportingProxy, PassOwnPtrWillBeRawPtr<WorkerThreadStartupData> startupData)
: m_threadID(0)
, m_workerLoaderProxy(workerLoaderProxy)
, m_workerReportingProxy(workerReportingProxy)
, m_startupData(startupData)
, m_notificationClient(0)
, m_shutdownEvent(adoptPtr(blink::Platform::current()->createWaitableEvent()))
{
MutexLocker lock(threadSetMutex());
workerThreads().add(this);
}
WorkerThread::~WorkerThread()
{
MutexLocker lock(threadSetMutex());
ASSERT(workerThreads().contains(this));
workerThreads().remove(this);
}
bool WorkerThread::start()
{
MutexLocker lock(m_threadCreationMutex);
if (m_threadID)
return true;
m_threadID = createThread(WorkerThread::workerThreadStart, this, "WebCore: Worker");
return m_threadID;
}
void WorkerThread::workerThreadStart(void* thread)
{
static_cast<WorkerThread*>(thread)->workerThread();
}
void WorkerThread::workerThread()
{
KURL scriptURL = m_startupData->m_scriptURL;
String sourceCode = m_startupData->m_sourceCode;
WorkerThreadStartMode startMode = m_startupData->m_startMode;
{
MutexLocker lock(m_threadCreationMutex);
ThreadState::attach();
m_workerGlobalScope = createWorkerGlobalScope(m_startupData.release());
m_runLoop.setWorkerGlobalScope(workerGlobalScope());
if (m_runLoop.terminated()) {
m_workerGlobalScope->script()->forbidExecution();
}
}
blink::Platform::current()->didStartWorkerRunLoop(blink::WebWorkerRunLoop(&m_runLoop));
m_workerReportingProxy.workerGlobalScopeStarted(m_workerGlobalScope.get());
WorkerScriptController* script = m_workerGlobalScope->script();
InspectorInstrumentation::willEvaluateWorkerScript(workerGlobalScope(), startMode);
script->evaluate(ScriptSourceCode(sourceCode, scriptURL));
runEventLoop();
ThreadIdentifier threadID = m_threadID;
#if ENABLE(OILPAN)
m_workerGlobalScope->dispose();
#else
ASSERT(m_workerGlobalScope->hasOneRef());
#endif
m_workerGlobalScope = nullptr;
ThreadState::detach();
workerReportingProxy().workerGlobalScopeDestroyed();
PlatformThreadData::current().destroy();
detachThread(threadID);
}
void WorkerThread::runEventLoop()
{
m_runLoop.run();
}
class WorkerThreadShutdownFinishTask : public ExecutionContextTask {
public:
static PassOwnPtr<WorkerThreadShutdownFinishTask> create()
{
return adoptPtr(new WorkerThreadShutdownFinishTask());
}
virtual void performTask(ExecutionContext *context)
{
WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
workerGlobalScope->clearInspector();
workerGlobalScope->clearScript();
}
virtual bool isCleanupTask() const { return true; }
};
class WorkerThreadShutdownStartTask : public ExecutionContextTask {
public:
static PassOwnPtr<WorkerThreadShutdownStartTask> create()
{
return adoptPtr(new WorkerThreadShutdownStartTask());
}
virtual void performTask(ExecutionContext *context)
{
WorkerGlobalScope* workerGlobalScope = toWorkerGlobalScope(context);
workerGlobalScope->stopActiveDOMObjects();
workerGlobalScope->removeAllEventListeners();
workerGlobalScope->postTask(WorkerThreadShutdownFinishTask::create());
}
virtual bool isCleanupTask() const { return true; }
};
void WorkerThread::stop()
{
ThreadState::SafePointScope safePointScope(ThreadState::HeapPointersOnStack);
MutexLocker lock(m_threadCreationMutex);
if (m_shutdownEvent)
m_shutdownEvent->signal();
if (m_workerGlobalScope) {
m_workerGlobalScope->script()->scheduleExecutionTermination();
m_workerGlobalScope->willStopActiveDOMObjects();
m_runLoop.postTaskAndTerminate(WorkerThreadShutdownStartTask::create());
return;
}
m_runLoop.terminate();
}
bool WorkerThread::isCurrentThread() const
{
return m_threadID == currentThread();
}
class ReleaseFastMallocFreeMemoryTask : public ExecutionContextTask {
virtual void performTask(ExecutionContext*) OVERRIDE { WTF::releaseFastMallocFreeMemory(); }
};
void WorkerThread::releaseFastMallocFreeMemoryInAllThreads()
{
MutexLocker lock(threadSetMutex());
HashSet<WorkerThread*>& threads = workerThreads();
HashSet<WorkerThread*>::iterator end = threads.end();
for (HashSet<WorkerThread*>::iterator it = threads.begin(); it != end; ++it)
(*it)->runLoop().postTask(adoptPtr(new ReleaseFastMallocFreeMemoryTask));
}
}