#include "config.h"
#include "RunLoop.h"
#include <glib.h>
#include <wtf/MainThread.h>
namespace WTF {
RunLoop::RunLoop()
{
m_runLoopContext = isMainThread() ? g_main_context_default() : adoptGRef(g_main_context_new());
ASSERT(m_runLoopContext);
GRefPtr<GMainLoop> innermostLoop = adoptGRef(g_main_loop_new(m_runLoopContext.get(), FALSE));
ASSERT(innermostLoop);
m_runLoopMainLoops.append(innermostLoop);
}
RunLoop::~RunLoop()
{
for (int i = m_runLoopMainLoops.size() - 1; i >= 0; --i) {
if (!g_main_loop_is_running(m_runLoopMainLoops[i].get()))
continue;
g_main_loop_quit(m_runLoopMainLoops[i].get());
}
}
void RunLoop::run()
{
RunLoop& mainRunLoop = RunLoop::current();
GMainLoop* innermostLoop = mainRunLoop.innermostLoop();
if (!g_main_loop_is_running(innermostLoop)) {
g_main_loop_run(innermostLoop);
return;
}
GMainLoop* nestedMainLoop = g_main_loop_new(0, FALSE);
mainRunLoop.pushNestedMainLoop(nestedMainLoop);
g_main_loop_run(nestedMainLoop);
mainRunLoop.popNestedMainLoop();
}
GMainLoop* RunLoop::innermostLoop()
{
ASSERT(!m_runLoopMainLoops.isEmpty());
return m_runLoopMainLoops[0].get();
}
void RunLoop::pushNestedMainLoop(GMainLoop* nestedLoop)
{
ASSERT(!m_runLoopMainLoops.isEmpty());
m_runLoopMainLoops.append(adoptGRef(nestedLoop));
}
void RunLoop::popNestedMainLoop()
{
ASSERT(!m_runLoopMainLoops.isEmpty());
m_runLoopMainLoops.removeLast();
}
void RunLoop::stop()
{
ASSERT(!m_runLoopMainLoops.isEmpty());
GRefPtr<GMainLoop> lastMainLoop = m_runLoopMainLoops.last();
if (g_main_loop_is_running(lastMainLoop.get()))
g_main_loop_quit(lastMainLoop.get());
}
void RunLoop::wakeUp()
{
RefPtr<RunLoop> runLoop(this);
GMainLoopSource::createAndDeleteOnDestroy().schedule("[WebKit] RunLoop work", std::function<void()>([runLoop] {
runLoop->performWork();
}), G_PRIORITY_DEFAULT, nullptr, m_runLoopContext.get());
g_main_context_wakeup(m_runLoopContext.get());
}
RunLoop::TimerBase::TimerBase(RunLoop& runLoop)
: m_runLoop(runLoop)
{
}
RunLoop::TimerBase::~TimerBase()
{
stop();
}
void RunLoop::TimerBase::start(double fireInterval, bool repeat)
{
m_timerSource.scheduleAfterDelay("[WebKit] RunLoop::Timer", std::function<bool ()>([this, repeat] { fired(); return repeat; }),
std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::duration<double>(fireInterval)), G_PRIORITY_DEFAULT, nullptr, m_runLoop.m_runLoopContext.get());
}
void RunLoop::TimerBase::stop()
{
m_timerSource.cancel();
}
bool RunLoop::TimerBase::isActive() const
{
return m_timerSource.isScheduled();
}
}