GMainLoopSource.cpp [plain text]
#include "config.h"
#if USE(GLIB)
#include "GMainLoopSource.h"
#include <gio/gio.h>
namespace WTF {
GMainLoopSource& GMainLoopSource::createAndDeleteOnDestroy()
{
return *new GMainLoopSource(DeleteOnDestroy);
}
GMainLoopSource::GMainLoopSource()
: m_deleteOnDestroy(DoNotDeleteOnDestroy)
, m_status(Ready)
{
}
GMainLoopSource::GMainLoopSource(DeleteOnDestroyType deleteOnDestroy)
: m_deleteOnDestroy(deleteOnDestroy)
, m_status(Ready)
{
}
GMainLoopSource::~GMainLoopSource()
{
cancel();
}
bool GMainLoopSource::isScheduled() const
{
return m_status == Scheduled;
}
bool GMainLoopSource::isActive() const
{
return m_status != Ready;
}
void GMainLoopSource::cancel()
{
if (!m_source)
return;
GRefPtr<GSource> source;
m_source.swap(source);
if (m_cancellable)
g_cancellable_cancel(m_cancellable.get());
g_source_destroy(source.get());
destroy();
}
void GMainLoopSource::reset()
{
m_status = Ready;
m_source = nullptr;
m_cancellable = nullptr;
m_voidCallback = nullptr;
m_boolCallback = nullptr;
m_destroyCallback = nullptr;
}
void GMainLoopSource::scheduleIdleSource(const char* name, GSourceFunc sourceFunction, int priority, GMainContext* context)
{
ASSERT(m_status == Ready);
m_status = Scheduled;
m_source = adoptGRef(g_idle_source_new());
g_source_set_name(m_source.get(), name);
if (priority != G_PRIORITY_DEFAULT_IDLE)
g_source_set_priority(m_source.get(), priority);
g_source_set_callback(m_source.get(), sourceFunction, this, nullptr);
g_source_attach(m_source.get(), context);
}
void GMainLoopSource::schedule(const char* name, std::function<void ()> function, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_voidCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleIdleSource(name, reinterpret_cast<GSourceFunc>(voidSourceCallback), priority, context);
}
void GMainLoopSource::schedule(const char* name, std::function<bool ()> function, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_boolCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleIdleSource(name, reinterpret_cast<GSourceFunc>(boolSourceCallback), priority, context);
}
void GMainLoopSource::schedule(const char* name, std::function<bool (GIOCondition)> function, GSocket* socket, GIOCondition condition, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
ASSERT(m_status == Ready);
m_status = Scheduled;
m_socketCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
m_cancellable = adoptGRef(g_cancellable_new());
m_source = adoptGRef(g_socket_create_source(socket, condition, m_cancellable.get()));
g_source_set_name(m_source.get(), name);
g_source_set_callback(m_source.get(), reinterpret_cast<GSourceFunc>(socketSourceCallback), this, nullptr);
g_source_attach(m_source.get(), context);
}
void GMainLoopSource::scheduleTimeoutSource(const char* name, GSourceFunc sourceFunction, int priority, GMainContext* context)
{
ASSERT(m_status == Ready);
m_status = Scheduled;
ASSERT(m_source);
g_source_set_name(m_source.get(), name);
if (priority != G_PRIORITY_DEFAULT)
g_source_set_priority(m_source.get(), priority);
g_source_set_callback(m_source.get(), sourceFunction, this, nullptr);
g_source_attach(m_source.get(), context);
}
void GMainLoopSource::scheduleAfterDelay(const char* name, std::function<void ()> function, std::chrono::milliseconds delay, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_source = adoptGRef(g_timeout_source_new(delay.count()));
m_voidCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleTimeoutSource(name, reinterpret_cast<GSourceFunc>(voidSourceCallback), priority, context);
}
void GMainLoopSource::scheduleAfterDelay(const char* name, std::function<bool ()> function, std::chrono::milliseconds delay, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_source = adoptGRef(g_timeout_source_new(delay.count()));
m_boolCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleTimeoutSource(name, reinterpret_cast<GSourceFunc>(boolSourceCallback), priority, context);
}
void GMainLoopSource::scheduleAfterDelay(const char* name, std::function<void ()> function, std::chrono::seconds delay, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_source = adoptGRef(g_timeout_source_new_seconds(delay.count()));
m_voidCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleTimeoutSource(name, reinterpret_cast<GSourceFunc>(voidSourceCallback), priority, context);
}
void GMainLoopSource::scheduleAfterDelay(const char* name, std::function<bool ()> function, std::chrono::seconds delay, int priority, std::function<void ()> destroyFunction, GMainContext* context)
{
cancel();
m_source = adoptGRef(g_timeout_source_new_seconds(delay.count()));
m_boolCallback = WTF::move(function);
m_destroyCallback = WTF::move(destroyFunction);
scheduleTimeoutSource(name, reinterpret_cast<GSourceFunc>(boolSourceCallback), priority, context);
}
void GMainLoopSource::voidCallback()
{
if (!m_source)
return;
ASSERT(m_voidCallback);
ASSERT(m_status == Scheduled);
m_status = Dispatched;
GSource* source = m_source.get();
m_voidCallback();
if (source == m_source.get())
destroy();
}
bool GMainLoopSource::boolCallback()
{
if (!m_source)
return false;
ASSERT(m_boolCallback);
ASSERT(m_status == Scheduled || m_status == Dispatched);
m_status = Dispatched;
GSource* source = m_source.get();
bool retval = m_boolCallback();
if (!retval && source == m_source.get())
destroy();
return retval;
}
bool GMainLoopSource::socketCallback(GIOCondition condition)
{
if (!m_source)
return false;
ASSERT(m_socketCallback);
ASSERT(m_status == Scheduled || m_status == Dispatched);
m_status = Dispatched;
if (g_cancellable_is_cancelled(m_cancellable.get())) {
destroy();
return false;
}
GSource* source = m_source.get();
bool retval = m_socketCallback(condition);
if (!retval && source == m_source.get())
destroy();
return retval;
}
void GMainLoopSource::destroy()
{
auto destroyCallback = WTF::move(m_destroyCallback);
auto deleteOnDestroy = m_deleteOnDestroy;
reset();
if (destroyCallback)
destroyCallback();
if (deleteOnDestroy == DoNotDeleteOnDestroy)
return;
delete this;
}
gboolean GMainLoopSource::voidSourceCallback(GMainLoopSource* source)
{
source->voidCallback();
return G_SOURCE_REMOVE;
}
gboolean GMainLoopSource::boolSourceCallback(GMainLoopSource* source)
{
return source->boolCallback() == Continue;
}
gboolean GMainLoopSource::socketSourceCallback(GSocket*, GIOCondition condition, GMainLoopSource* source)
{
return source->socketCallback(condition) == Continue;
}
}
#endif // USE(GLIB)