summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/EventLoop')
-rw-r--r--Swiften/EventLoop/SConscript1
-rw-r--r--Swiften/EventLoop/SingleThreadedEventLoop.cpp65
-rw-r--r--Swiften/EventLoop/SingleThreadedEventLoop.h58
3 files changed, 124 insertions, 0 deletions
diff --git a/Swiften/EventLoop/SConscript b/Swiften/EventLoop/SConscript
index e448f43..b405f6b 100644
--- a/Swiften/EventLoop/SConscript
+++ b/Swiften/EventLoop/SConscript
@@ -6,6 +6,7 @@ sources = [
"Event.cpp",
"SimpleEventLoop.cpp",
"DummyEventLoop.cpp",
+ "SingleThreadedEventLoop.cpp",
]
objects = swiften_env.SwiftenObject(sources)
diff --git a/Swiften/EventLoop/SingleThreadedEventLoop.cpp b/Swiften/EventLoop/SingleThreadedEventLoop.cpp
new file mode 100644
index 0000000..4c5e209
--- /dev/null
+++ b/Swiften/EventLoop/SingleThreadedEventLoop.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010 Soren Dreijer
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#include "Swiften/EventLoop/SingleThreadedEventLoop.h"
+
+#include <boost/bind.hpp>
+#include <iostream>
+
+#include "Swiften/Base/foreach.h"
+
+
+namespace Swift {
+
+SingleThreadedEventLoop::SingleThreadedEventLoop()
+: shouldShutDown_(false)
+{
+}
+
+SingleThreadedEventLoop::~SingleThreadedEventLoop() {
+ if (!events_.empty()) {
+ std::cerr << "Warning: Pending events in SingleThreadedEventLoop at destruction time." << std::endl;
+ }
+}
+
+void SingleThreadedEventLoop::waitForEvents() {
+ boost::unique_lock<boost::mutex> lock(eventsMutex_);
+ while (events_.size() == 0 && !shouldShutDown_) {
+ eventsAvailable_.wait(lock);
+ }
+
+ if (shouldShutDown_)
+ throw EventLoopCanceledException();
+}
+
+void SingleThreadedEventLoop::handleEvents() {
+ // Make a copy of the list of events so we don't block any threads that post
+ // events while we process them.
+ std::vector<Event> events;
+ {
+ boost::unique_lock<boost::mutex> lock(eventsMutex_);
+ events.swap(events_);
+ }
+
+ // Loop through all the events and handle them
+ foreach(const Event& event, events) {
+ handleEvent(event);
+ }
+}
+
+void SingleThreadedEventLoop::stop() {
+ boost::unique_lock<boost::mutex> lock(eventsMutex_);
+ shouldShutDown_ = true;
+ eventsAvailable_.notify_one();
+}
+
+void SingleThreadedEventLoop::post(const Event& event) {
+ boost::lock_guard<boost::mutex> lock(eventsMutex_);
+ events_.push_back(event);
+ eventsAvailable_.notify_one();
+}
+
+} // namespace Swift
diff --git a/Swiften/EventLoop/SingleThreadedEventLoop.h b/Swiften/EventLoop/SingleThreadedEventLoop.h
new file mode 100644
index 0000000..75ffad0
--- /dev/null
+++ b/Swiften/EventLoop/SingleThreadedEventLoop.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2010 Soren Dreijer
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+
+#pragma once
+
+#include <vector>
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/condition_variable.hpp>
+
+#include "Swiften/EventLoop/EventLoop.h"
+
+// DESCRIPTION:
+//
+// All interaction with Swiften should happen on the same thread, such as the main GUI thread,
+// since the library isn't thread-safe.
+// For applications that don't have a main loop, such as WPF and MFC applications, we need a
+// different approach to process events from Swiften.
+//
+// The SingleThreadedEventLoop class implements an event loop that can be used from such applications.
+//
+// USAGE:
+//
+// Spawn a new thread in the desired framework and call SingleThreadedEventLoop::waitForEvents(). The method
+// blocks until a new event has arrived at which time it'll return, or until the wait is canceled
+// at which time it throws EventLoopCanceledException.
+//
+// When a new event has arrived and SingleThreadedEventLoop::waitForEvents() returns, the caller should then
+// call SingleThreadedEventLoop::handleEvents() on the main GUI thread. For WPF applications, for instance,
+// the Dispatcher class can be used to execute the call on the GUI thread.
+//
+
+namespace Swift {
+ class SingleThreadedEventLoop : public EventLoop {
+ public:
+ class EventLoopCanceledException : public std::exception { };
+
+ public:
+ SingleThreadedEventLoop();
+ ~SingleThreadedEventLoop();
+
+ // Blocks while waiting for new events and returns when new events are available.
+ // Throws EventLoopCanceledException when the wait is canceled.
+ void waitForEvents();
+ void handleEvents();
+ void stop();
+
+ virtual void post(const Event& event);
+
+ private:
+ bool shouldShutDown_;
+ std::vector<Event> events_;
+ boost::mutex eventsMutex_;
+ boost::condition_variable eventsAvailable_;
+ };
+}