// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "modules/compositorworker/CompositorWorkerThread.h"

#include "bindings/core/v8/V8GCController.h"
#include "bindings/core/v8/V8Initializer.h"
#include "core/workers/InProcessWorkerObjectProxy.h"
#include "core/workers/WorkerBackingThread.h"
#include "core/workers/WorkerThreadStartupData.h"
#include "modules/compositorworker/CompositorWorkerGlobalScope.h"
#include "platform/ThreadSafeFunctional.h"
#include "platform/TraceEvent.h"
#include "platform/WaitableEvent.h"
#include "platform/WebThreadSupportingGC.h"
#include "public/platform/Platform.h"

namespace blink {

namespace {

// This is a singleton class holding the compositor worker thread in this
// renderer process. BackingThreadHolder::m_thread is cleared by
// ModulesInitializer::shutdown.
// See WorkerThread::terminateAndWaitForAllWorkers for the process shutdown
// case.
class BackingThreadHolder {
public:
    static BackingThreadHolder& instance()
    {
        MutexLocker locker(holderInstanceMutex());
        return *s_instance;
    }

    static void ensureInstance()
    {
        if (!s_instance)
            s_instance = new BackingThreadHolder;
    }

    static void terminateExecution()
    {
        MutexLocker locker(holderInstanceMutex());
        if (s_instance && s_instance->m_initialized) {
            s_instance->thread()->isolate()->TerminateExecution();
            s_instance->m_terminatingExecution = true;
        }
    }

    static void clear()
    {
        MutexLocker locker(holderInstanceMutex());
        if (s_instance) {
            DCHECK(!s_instance->m_initialized || s_instance->m_terminatingExecution);
            s_instance->shutdownAndWait();
            delete s_instance;
            s_instance = nullptr;
        }
    }

    static void createForTest()
    {
        MutexLocker locker(holderInstanceMutex());
        DCHECK_EQ(nullptr, s_instance);
        s_instance = new BackingThreadHolder(WorkerBackingThread::createForTest(Platform::current()->compositorThread()));
    }

    WorkerBackingThread* thread() { return m_thread.get(); }

private:
    BackingThreadHolder(PassOwnPtr<WorkerBackingThread> useBackingThread = nullptr)
        : m_thread(useBackingThread ? std::move(useBackingThread) : WorkerBackingThread::create(Platform::current()->compositorThread()))
    {
        DCHECK(isMainThread());
        m_thread->backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&BackingThreadHolder::initializeOnThread, AllowCrossThreadAccess(this)));
    }

    static Mutex& holderInstanceMutex()
    {
        DEFINE_THREAD_SAFE_STATIC_LOCAL(Mutex, holderMutex, new Mutex);
        return holderMutex;
    }

    void initializeOnThread()
    {
        MutexLocker locker(holderInstanceMutex());
        DCHECK_EQ(0u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the first to attach to WorkerBackingThread";
        m_thread->attach();
        m_initialized = true;
    }

    void shutdownAndWait()
    {
        DCHECK(isMainThread());
        WaitableEvent doneEvent;
        m_thread->backingThread().postTask(BLINK_FROM_HERE, threadSafeBind(&BackingThreadHolder::shutdownOnThread, AllowCrossThreadAccess(this), AllowCrossThreadAccess(&doneEvent)));
        doneEvent.wait();
    }

    void shutdownOnThread(WaitableEvent* doneEvent)
    {
        DCHECK_EQ(1u, m_thread->workerScriptCount()) << "BackingThreadHolder should be the last to detach from WorkerBackingThread";
        m_thread->detach();
        doneEvent->signal();
    }

    OwnPtr<WorkerBackingThread> m_thread;
    bool m_terminatingExecution = false;
    bool m_initialized = false;

    static BackingThreadHolder* s_instance;
};

BackingThreadHolder* BackingThreadHolder::s_instance = nullptr;

} // namespace

PassOwnPtr<CompositorWorkerThread> CompositorWorkerThread::create(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, InProcessWorkerObjectProxy& workerObjectProxy, double timeOrigin)
{
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("compositor-worker"), "CompositorWorkerThread::create");
    ASSERT(isMainThread());
    return adoptPtr(new CompositorWorkerThread(workerLoaderProxy, workerObjectProxy, timeOrigin));
}

CompositorWorkerThread::CompositorWorkerThread(PassRefPtr<WorkerLoaderProxy> workerLoaderProxy, InProcessWorkerObjectProxy& workerObjectProxy, double timeOrigin)
    : WorkerThread(workerLoaderProxy, workerObjectProxy)
    , m_workerObjectProxy(workerObjectProxy)
    , m_timeOrigin(timeOrigin)
{
}

CompositorWorkerThread::~CompositorWorkerThread()
{
}

WorkerBackingThread& CompositorWorkerThread::workerBackingThread()
{
    return *BackingThreadHolder::instance().thread();
}

WorkerGlobalScope*CompositorWorkerThread::createWorkerGlobalScope(PassOwnPtr<WorkerThreadStartupData> startupData)
{
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("compositor-worker"), "CompositorWorkerThread::createWorkerGlobalScope");
    return CompositorWorkerGlobalScope::create(this, std::move(startupData), m_timeOrigin);
}

void CompositorWorkerThread::ensureSharedBackingThread()
{
    DCHECK(isMainThread());
    BackingThreadHolder::ensureInstance();
}

void CompositorWorkerThread::terminateExecution()
{
    DCHECK(isMainThread());
    BackingThreadHolder::terminateExecution();
}

void CompositorWorkerThread::clearSharedBackingThread()
{
    DCHECK(isMainThread());
    BackingThreadHolder::clear();
}

void CompositorWorkerThread::createSharedBackingThreadForTest()
{
    BackingThreadHolder::createForTest();
}

} // namespace blink
