Skip to content

Commit

Permalink
Added test for ASYNC event loop
Browse files Browse the repository at this point in the history
  • Loading branch information
tmeshkova committed Oct 15, 2014
1 parent a194ae0 commit f8b3cf2
Show file tree
Hide file tree
Showing 7 changed files with 306 additions and 11 deletions.
11 changes: 0 additions & 11 deletions embedding/embedlite/tests/Makefile.in
Expand Up @@ -10,17 +10,6 @@ relativesrcdir = @relativesrcdir@

include $(DEPTH)/config/autoconf.mk

DEFINES += -DXPCOM_GLUE
# move me to common, when we link with common library
STL_FLAGS=

LOCAL_INCLUDES += -I$(topsrcdir)/xpcom/build

LOCAL_INCLUDES = \
$(TK_CFLAGS) \
$(MOZ_GTHREAD_CFLAGS) \
$(NULL)

NSDISTMODE = copy

include $(topsrcdir)/config/config.mk
Expand Down
2 changes: 2 additions & 0 deletions embedding/embedlite/tests/moz.build
Expand Up @@ -3,6 +3,8 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

DIRS += ['qtasync']

SimplePrograms([
'embedLiteCoreInitTest',
'embedLiteViewInitTest',
Expand Down
16 changes: 16 additions & 0 deletions embedding/embedlite/tests/qtasync/Makefile.in
@@ -0,0 +1,16 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

DEPTH = @DEPTH@
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
relativesrcdir = @relativesrcdir@

include $(DEPTH)/config/autoconf.mk

NSDISTMODE = copy

include $(topsrcdir)/config/config.mk
include $(topsrcdir)/config/rules.mk
67 changes: 67 additions & 0 deletions embedding/embedlite/tests/qtasync/embedLiteCoreInitTestAsync.cpp
@@ -0,0 +1,67 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/embedlite/EmbedInitGlue.h"
#include "mozilla/embedlite/EmbedLiteApp.h"
#include "qmessagepump.h"

#ifdef MOZ_WIDGET_QT
#include <QGuiApplication>
#endif

using namespace mozilla::embedlite;

class MyListener : public EmbedLiteAppListener
{
public:
MyListener(EmbedLiteApp* aApp) : mApp(aApp) {
}
virtual ~MyListener() { }
virtual void Initialized() {
printf("Embedding initialized\n");
mApp->PostTask(&MyListener::StopEmbedding, this);
}
virtual void Destroyed() {
printf("Embedding destroyed\n");
}
static void StopEmbedding(void* aData) {
printf("StopEmbedding\n");
MyListener* self = static_cast<MyListener*>(aData);
self->mApp->Stop();
printf("Embedding stop finished\n");
}

private:
EmbedLiteApp* mApp;
};

int main(int argc, char** argv)
{
#ifdef MOZ_WIDGET_QT
QGuiApplication app(argc, argv);
#endif

printf("Load XUL Symbols\n");
if (LoadEmbedLite(argc, argv)) {
printf("XUL Symbols loaded\n");
EmbedLiteApp* mapp = XRE_GetEmbedLite();
MyListener* listener = new MyListener(mapp);
mapp->SetListener(listener);
MessagePumpQt* mQtPump = new MessagePumpQt(mapp);
bool res = mapp->StartWithCustomPump(EmbedLiteApp::EMBED_THREAD, mQtPump->EmbedLoop());
printf("XUL Symbols loaded: init res:%i\n", res);
app.exec();
printf("Execution stopped\n");
mapp->SetListener(nullptr);
printf("Listener is null\n");
delete listener;
printf("Listener destroed\n");
delete mapp;
printf("App destroed\n");
} else {
printf("XUL Symbols failed to load\n");
}
return 0;
}
26 changes: 26 additions & 0 deletions embedding/embedlite/tests/qtasync/moz.build
@@ -0,0 +1,26 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

Program('embedLiteCoreInitTestAsync')

GENERATED_SOURCES += [
'moc_qmessagepump.cpp',
]

SOURCES += [
'embedLiteCoreInitTestAsync.cpp',
'qmessagepump.cpp',
]

DEFINES['XPCOM_GLUE'] = True
DISABLE_STL_WRAPPING = True

USE_LIBS += [
'xpcomglue',
]

OS_LIBS += CONFIG['TK_LIBS']
CXXFLAGS += CONFIG['TK_CFLAGS']
132 changes: 132 additions & 0 deletions embedding/embedlite/tests/qtasync/qmessagepump.cpp
@@ -0,0 +1,132 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* vim: set ts=2 sw=2 et tw=79: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#include <QTimer>
#include <QEvent>
#include <QThread>
#include <QAbstractEventDispatcher>
#include <QGuiApplication>

#include "qmessagepump.h"

#include "mozilla/embedlite/EmbedLiteMessagePump.h"
#include "mozilla/embedlite/EmbedLiteApp.h"

using namespace mozilla::embedlite;

namespace {
// Cached QEvent user type, registered for our event system
static int sPokeEvent;
} // namespace

MessagePumpQt::MessagePumpQt(EmbedLiteApp* aApp)
: mApp(aApp), mTimer(new QTimer(this)), state_(0), mLastDelayedWorkTime(-1)
{
mEventLoopPrivate = mApp->CreateEmbedLiteMessagePump(this);
// Register our custom event type, to use in qApp event loop
sPokeEvent = QEvent::registerEventType();
connect(mTimer, SIGNAL(timeout()), this, SLOT(dispatchDelayed()));
mTimer->setSingleShot(true);
}

MessagePumpQt::~MessagePumpQt()
{
mTimer->stop();
delete mTimer;
delete state_;
delete mEventLoopPrivate;
}

bool
MessagePumpQt::event(QEvent *e)
{
if (e->type() == sPokeEvent) {
HandleDispatch();
return true;
}
return QObject::event(e);
}

void MessagePumpQt::HandleDispatch()
{
if (state_->should_quit) {
return;
}

if (mEventLoopPrivate->DoWork(state_->delegate)) {
// there might be more, see more_work_is_plausible
// variable above, that's why we ScheduleWork() to keep going.
ScheduleWorkLocal();
}

if (state_->should_quit) {
return;
}

bool doIdleWork = !mEventLoopPrivate->DoDelayedWork(state_->delegate);
scheduleDelayedIfNeeded();

if (doIdleWork) {
if (mEventLoopPrivate->DoIdleWork(state_->delegate)) {
ScheduleWorkLocal();
}
}
}

void MessagePumpQt::ScheduleWorkLocal()
{
QCoreApplication::postEvent(this,
new QEvent((QEvent::Type)sPokeEvent));
}

void
MessagePumpQt::scheduleDelayedIfNeeded()
{
if (mLastDelayedWorkTime == -1) {
return;
}

if (mTimer->isActive()) {
mTimer->stop();
}

mTimer->start(mLastDelayedWorkTime >= 0 ? mLastDelayedWorkTime : 0);
}

void
MessagePumpQt::dispatchDelayed()
{
HandleDispatch();
}

void MessagePumpQt::Run(void* delegate)
{
RunState* state = new RunState();
state->delegate = delegate;
state->should_quit = false;
state->run_depth = state_ ? state_->run_depth + 1 : 1;
state_ = state;
HandleDispatch();
}

void MessagePumpQt::Quit()
{
if (state_) {
state_->should_quit = true;
state_->delegate = NULL;
}
}

void MessagePumpQt::ScheduleWork()
{
ScheduleWorkLocal();
}

void MessagePumpQt::ScheduleDelayedWork(const int aDelay)
{
mLastDelayedWorkTime = aDelay;
scheduleDelayedIfNeeded();
}
63 changes: 63 additions & 0 deletions embedding/embedlite/tests/qtasync/qmessagepump.h
@@ -0,0 +1,63 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* vim: set ts=2 sw=2 et tw=79: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef qmessagepump_h
#define qmessagepump_h

#include <QObject>
#include <QTimer>
#include <QVariant>
#include <QStringList>
#include "mozilla/embedlite/EmbedLiteMessagePump.h"

namespace mozilla {
namespace embedlite {
class EmbedLiteApp;
}}

class MessagePumpQt : public QObject, public mozilla::embedlite::EmbedLiteMessagePumpListener
{
Q_OBJECT

public:
MessagePumpQt(mozilla::embedlite::EmbedLiteApp* aApp);
~MessagePumpQt();

virtual bool event(QEvent* e);
void scheduleDelayedIfNeeded();
void HandleDispatch();
void ScheduleWork();

virtual void Run(void* aDelegate);
virtual void Quit();
virtual void ScheduleWorkLocal();
virtual void ScheduleDelayedWork(const int aDelay);

mozilla::embedlite::EmbedLiteMessagePump* EmbedLoop() { return mEventLoopPrivate; }

public Q_SLOTS:
void dispatchDelayed();

private:
// We may make recursive calls to Run, so we save state that needs to be
// separate between them in this structure type.
struct RunState {
void* delegate;
// Used to flag that the current Run() invocation should return ASAP.
bool should_quit;
// Used to count how many Run() invocations are on the stack.
int run_depth;
};

mozilla::embedlite::EmbedLiteApp* mApp;
mozilla::embedlite::EmbedLiteMessagePump* mEventLoopPrivate;
QTimer* mTimer;
RunState* state_;
int mLastDelayedWorkTime;
bool mStarted;
};

#endif /* qmessagepump_h */

0 comments on commit f8b3cf2

Please sign in to comment.