Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / scheduler / Scheduler.cpp
index c88c420..b91644a 100644 (file)
 #include "config.h"
 #include "platform/scheduler/Scheduler.h"
 
-#include "platform/PlatformThreadData.h"
-#include "platform/Task.h"
-#include "platform/ThreadTimers.h"
-#include "platform/TraceEvent.h"
+#include "platform/TraceLocation.h"
 #include "public/platform/Platform.h"
-#include "wtf/MainThread.h"
+#include "public/platform/WebScheduler.h"
+#include "public/platform/WebTraceLocation.h"
 
 namespace blink {
 
-namespace {
-
-// The time we should stay in CompositorPriority mode for, after a touch event.
-double kLowSchedulerPolicyAfterTouchTimeSeconds = 0.1;
-
-// Can be created from any thread.
-// Note if the scheduler gets shutdown, this may be run after.
-class MainThreadIdleTaskAdapter : public WebThread::Task {
+class IdleTaskRunner : public WebScheduler::IdleTask {
 public:
-    MainThreadIdleTaskAdapter(const Scheduler::IdleTask& idleTask, double allottedTimeMs, const TraceLocation& location)
-        : m_idleTask(idleTask)
-        , m_allottedTimeMs(allottedTimeMs)
-        , m_location(location)
+    explicit IdleTaskRunner(const Scheduler::IdleTask& task)
+        : m_task(task)
     {
     }
 
-    // WebThread::Task implementation.
-    virtual void run() OVERRIDE
-    {
-        TRACE_EVENT2("blink", "MainThreadIdleTaskAdapter::run",
-            "src_file", m_location.fileName(),
-            "src_func", m_location.functionName());
-        m_idleTask(m_allottedTimeMs);
-    }
-
-private:
-    Scheduler::IdleTask m_idleTask;
-    double m_allottedTimeMs;
-    TraceLocation m_location;
-};
-
-} // namespace
-
-// Typically only created from compositor or render threads.
-// Note if the scheduler gets shutdown, this may be run after.
-class Scheduler::MainThreadPendingHighPriorityTaskRunner : public WebThread::Task {
-public:
-    MainThreadPendingHighPriorityTaskRunner()
+    virtual ~IdleTaskRunner()
     {
-        ASSERT(Scheduler::shared());
     }
 
-    // WebThread::Task implementation.
-    virtual void run() OVERRIDE
+    // WebScheduler::IdleTask implementation.
+    void run(double deadlineSeconds) override
     {
-        Scheduler* scheduler = Scheduler::shared();
-        // FIXME: This check should't be necessary, tasks should not outlive blink.
-        ASSERT(scheduler);
-        if (!scheduler)
-            return;
-        // NOTE we must unconditionally execute high priority tasks here, since if we're not in CompositorPriority
-        // mode, then this is the only place where high priority tasks will be executed.
-        scheduler->swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting();
+        m_task(deadlineSeconds);
     }
-};
-
-
-// Can be created from any thread.
-// Note if the scheduler gets shutdown, this may be run after.
-class Scheduler::MainThreadPendingTaskRunner : public WebThread::Task {
-public:
-    MainThreadPendingTaskRunner(
-        const Scheduler::Task& task, const TraceLocation& location, const char* traceName)
-        : m_task(task, location, traceName)
-    {
-        ASSERT(Scheduler::shared());
-    }
-
-    // WebThread::Task implementation.
-    virtual void run() OVERRIDE
-    {
-        Scheduler* scheduler = Scheduler::shared();
-        // FIXME: This check should't be necessary, tasks should not outlive blink.
-        ASSERT(scheduler);
-        if (scheduler)
-            Scheduler::shared()->runPendingHighPriorityTasksIfInCompositorPriority();
-        m_task.run();
-    }
-
-    TracedTask m_task;
+private:
+    Scheduler::IdleTask m_task;
 };
 
 Scheduler* Scheduler::s_sharedScheduler = nullptr;
 
-void Scheduler::initializeOnMainThread()
-{
-    s_sharedScheduler = new Scheduler();
-}
-
 void Scheduler::shutdown()
 {
     delete s_sharedScheduler;
@@ -111,231 +42,33 @@ void Scheduler::shutdown()
 
 Scheduler* Scheduler::shared()
 {
+    if (!s_sharedScheduler)
+        s_sharedScheduler = new Scheduler(Platform::current()->scheduler());
     return s_sharedScheduler;
 }
 
-Scheduler::Scheduler()
-    : m_sharedTimerFunction(nullptr)
-    , m_mainThread(blink::Platform::current()->currentThread())
-    , m_compositorPriorityPolicyEndTimeSeconds(0)
-    , m_highPriorityTaskCount(0)
-    , m_highPriorityTaskRunnerPosted(false)
-    , m_schedulerPolicy(Normal)
+Scheduler::Scheduler(WebScheduler* webScheduler)
+    : m_webScheduler(webScheduler)
 {
 }
 
 Scheduler::~Scheduler()
 {
-    while (hasPendingHighPriorityWork()) {
-        swapQueuesAndRunPendingTasks();
-    }
-}
-
-void Scheduler::willBeginFrame(const WebBeginFrameArgs& args)
-{
-    // TODO: Use frame deadline and interval to schedule idle tasks.
-}
-
-void Scheduler::didCommitFrameToCompositor()
-{
-    // TODO: Trigger the frame deadline immediately.
-}
-
-void Scheduler::scheduleIdleTask(const TraceLocation& location, const IdleTask& idleTask)
-{
-    // TODO: send a real allottedTime here.
-    m_mainThread->postTask(new MainThreadIdleTaskAdapter(idleTask, 0, location));
-}
-
-void Scheduler::postHighPriorityTaskInternal(const TraceLocation& location, const Task& task, const char* traceName)
-{
-    Locker<Mutex> lock(m_pendingTasksMutex);
-
-    m_pendingHighPriorityTasks.append(TracedTask(task, location, traceName));
-    atomicIncrement(&m_highPriorityTaskCount);
-    maybePostMainThreadPendingHighPriorityTaskRunner();
-    TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
-}
-
-void Scheduler::postTask(const TraceLocation& location, const Task& task)
-{
-    m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::MainThreadTask"));
-}
-
-void Scheduler::postInputTask(const TraceLocation& location, const Task& task)
-{
-    postHighPriorityTaskInternal(location, task, "Scheduler::InputTask");
-}
-
-void Scheduler::didReceiveInputEvent()
-{
-    enterSchedulerPolicy(CompositorPriority);
-}
-
-void Scheduler::postCompositorTask(const TraceLocation& location, const Task& task)
-{
-    postHighPriorityTaskInternal(location, task, "Scheduler::CompositorTask");
-}
-
-void Scheduler::postIpcTask(const TraceLocation& location, const Task& task)
-{
-    // FIXME: we want IPCs to be high priority, but we can't currently do that because some of them can take a very long
-    // time to process. These need refactoring but we need to add some infrastructure to identify them.
-    m_mainThread->postTask(new MainThreadPendingTaskRunner(task, location, "Scheduler::IpcTask"));
-}
-
-void Scheduler::maybePostMainThreadPendingHighPriorityTaskRunner()
-{
-    ASSERT(m_pendingTasksMutex.locked());
-    if (m_highPriorityTaskRunnerPosted)
-        return;
-    m_mainThread->postTask(new MainThreadPendingHighPriorityTaskRunner());
-    m_highPriorityTaskRunnerPosted = true;
+    if (m_webScheduler)
+        m_webScheduler->shutdown();
 }
 
 void Scheduler::postIdleTask(const TraceLocation& location, const IdleTask& idleTask)
 {
-    scheduleIdleTask(location, idleTask);
-}
-
-void Scheduler::tickSharedTimer()
-{
-    TRACE_EVENT0("blink", "Scheduler::tickSharedTimer");
-
-    // Run any high priority tasks that are queued up, otherwise the blink timers will yield immediately.
-    bool workDone = runPendingHighPriorityTasksIfInCompositorPriority();
-    m_sharedTimerFunction();
-
-    // The blink timers may have just yielded, so run any high priority tasks that where queued up
-    // while the blink timers were executing.
-    if (!workDone)
-        runPendingHighPriorityTasksIfInCompositorPriority();
-}
-
-bool Scheduler::runPendingHighPriorityTasksIfInCompositorPriority()
-{
-    ASSERT(isMainThread());
-    if (schedulerPolicy() != CompositorPriority)
-        return false;
-
-    return swapQueuesAndRunPendingTasks();
-}
-
-bool Scheduler::swapQueuesAndRunPendingTasks()
-{
-    ASSERT(isMainThread());
-
-    // These locks guard against another thread posting input or compositor tasks while we swap the buffers.
-    // One the buffers have been swapped we can safely access the returned deque without having to lock.
-    m_pendingTasksMutex.lock();
-    Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
-    maybeEnterNormalSchedulerPolicy();
-    m_pendingTasksMutex.unlock();
-    return executeHighPriorityTasks(highPriorityTasks);
-}
-
-void Scheduler::swapQueuesRunPendingTasksAndAllowHighPriorityTaskRunnerPosting()
-{
-    ASSERT(isMainThread());
-
-    // These locks guard against another thread posting input or compositor tasks while we swap the buffers.
-    // One the buffers have been swapped we can safely access the returned deque without having to lock.
-    m_pendingTasksMutex.lock();
-    Deque<TracedTask>& highPriorityTasks = m_pendingHighPriorityTasks.swapBuffers();
-    m_highPriorityTaskRunnerPosted = false;
-    maybeEnterNormalSchedulerPolicy();
-    m_pendingTasksMutex.unlock();
-    executeHighPriorityTasks(highPriorityTasks);
-}
-
-void Scheduler::maybeEnterNormalSchedulerPolicy()
-{
-    ASSERT(isMainThread());
-    ASSERT(m_pendingTasksMutex.locked());
-
-    // Go back to the normal scheduler policy if enough time has elapsed.
-    if (schedulerPolicy() == CompositorPriority && Platform::current()->monotonicallyIncreasingTime() > m_compositorPriorityPolicyEndTimeSeconds)
-        enterSchedulerPolicyLocked(Normal);
-}
-
-bool Scheduler::executeHighPriorityTasks(Deque<TracedTask>& highPriorityTasks)
-{
-    TRACE_EVENT0("blink", "Scheduler::executeHighPriorityTasks");
-    int highPriorityTasksExecuted = 0;
-    while (!highPriorityTasks.isEmpty()) {
-        highPriorityTasks.takeFirst().run();
-        highPriorityTasksExecuted++;
-    }
-
-    int highPriorityTaskCount = atomicSubtract(&m_highPriorityTaskCount, highPriorityTasksExecuted);
-    ASSERT_UNUSED(highPriorityTaskCount, highPriorityTaskCount >= 0);
-    TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "PendingHighPriorityTasks", m_highPriorityTaskCount);
-    return highPriorityTasksExecuted > 0;
-}
-
-void Scheduler::sharedTimerAdapter()
-{
-    shared()->tickSharedTimer();
-}
-
-void Scheduler::setSharedTimerFiredFunction(void (*function)())
-{
-    m_sharedTimerFunction = function;
-    blink::Platform::current()->setSharedTimerFiredFunction(function ? &Scheduler::sharedTimerAdapter : nullptr);
-}
-
-void Scheduler::setSharedTimerFireInterval(double interval)
-{
-    blink::Platform::current()->setSharedTimerFireInterval(interval);
-}
-
-void Scheduler::stopSharedTimer()
-{
-    blink::Platform::current()->stopSharedTimer();
+    if (m_webScheduler)
+        m_webScheduler->postIdleTask(WebTraceLocation(location), new IdleTaskRunner(idleTask));
 }
 
 bool Scheduler::shouldYieldForHighPriorityWork() const
 {
-    // It's only worthwhile yielding in CompositorPriority mode.
-    if (schedulerPolicy() != CompositorPriority)
-        return false;
-
-    return hasPendingHighPriorityWork();
-}
-
-bool Scheduler::hasPendingHighPriorityWork() const
-{
-    // This method is expected to be run on the main thread, but the high priority tasks will be posted by
-    // other threads. We could use locks here, but this function is (sometimes) called a lot by
-    // ThreadTimers::sharedTimerFiredInternal so we decided to use atomics + barrier loads here which
-    // should be cheaper.
-    // NOTE it's possible the barrier read is overkill here, since delayed yielding isn't a big deal.
-    return acquireLoad(&m_highPriorityTaskCount) != 0;
-}
-
-Scheduler::SchedulerPolicy Scheduler::schedulerPolicy() const
-{
-    ASSERT(isMainThread());
-    // It's important not to miss the transition from normal to low latency mode, otherwise we're likely to
-    // delay the processing of input tasks. Since that transition is triggered by a different thread, we
-    // need either a lock or a memory barrier, and the memory barrier is probably cheaper.
-    return static_cast<SchedulerPolicy>(acquireLoad(&m_schedulerPolicy));
-}
-
-void Scheduler::enterSchedulerPolicy(SchedulerPolicy schedulerPolicy)
-{
-    Locker<Mutex> lock(m_pendingTasksMutex);
-    enterSchedulerPolicyLocked(schedulerPolicy);
-}
-
-void Scheduler::enterSchedulerPolicyLocked(SchedulerPolicy schedulerPolicy)
-{
-    ASSERT(m_pendingTasksMutex.locked());
-    if (schedulerPolicy == CompositorPriority)
-        m_compositorPriorityPolicyEndTimeSeconds = Platform::current()->monotonicallyIncreasingTime() + kLowSchedulerPolicyAfterTouchTimeSeconds;
-
-    releaseStore(&m_schedulerPolicy, schedulerPolicy);
-    TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink.scheduler"), "SchedulerPolicy", schedulerPolicy);
+    if (m_webScheduler)
+        return m_webScheduler->shouldYieldForHighPriorityWork();
+    return false;
 }
 
 } // namespace blink