diff options
Diffstat (limited to 'Swiften/EventLoop')
-rw-r--r-- | Swiften/EventLoop/SConscript | 1 | ||||
-rw-r--r-- | Swiften/EventLoop/SingleThreadedEventLoop.cpp | 65 | ||||
-rw-r--r-- | Swiften/EventLoop/SingleThreadedEventLoop.h | 58 |
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_; + }; +} |