diff options
author | Remko Tronçon <git@el-tramo.be> | 2009-06-01 08:48:42 (GMT) |
---|---|---|
committer | Remko Tronçon <git@el-tramo.be> | 2009-06-01 09:24:28 (GMT) |
commit | 2812bddd81f8a1b804c7460f4e14cd0aa393d129 (patch) | |
tree | d46294f35150c4f0f43deaf2d31fceaf945ae715 /3rdParty/Boost/libs/signals | |
download | swift-contrib-2812bddd81f8a1b804c7460f4e14cd0aa393d129.zip swift-contrib-2812bddd81f8a1b804c7460f4e14cd0aa393d129.tar.bz2 |
Import.
Diffstat (limited to '3rdParty/Boost/libs/signals')
-rw-r--r-- | 3rdParty/Boost/libs/signals/src/connection.cpp | 155 | ||||
-rw-r--r-- | 3rdParty/Boost/libs/signals/src/named_slot_map.cpp | 134 | ||||
-rw-r--r-- | 3rdParty/Boost/libs/signals/src/signal_base.cpp | 189 | ||||
-rw-r--r-- | 3rdParty/Boost/libs/signals/src/slot.cpp | 71 | ||||
-rw-r--r-- | 3rdParty/Boost/libs/signals/src/trackable.cpp | 59 |
5 files changed, 608 insertions, 0 deletions
diff --git a/3rdParty/Boost/libs/signals/src/connection.cpp b/3rdParty/Boost/libs/signals/src/connection.cpp new file mode 100644 index 0000000..b4ed8b4 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/connection.cpp @@ -0,0 +1,155 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/connection.hpp> +#include <cassert> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + + connection::connection(const connection& other) : + con(other.con), controlling_connection(other.controlling_connection) + { + } + + connection::~connection() + { + if (controlling_connection) { + disconnect(); + } + } + + void + connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con) + { + con.reset(new_con); + } + + bool connection::operator==(const connection& other) const + { + return con.get() == other.con.get(); + } + + bool connection::operator<(const connection& other) const + { + return con.get() < other.con.get(); + } + + connection& connection::operator=(const connection& other) + { + connection(other).swap(*this); + return *this; + } + + void connection::swap(connection& other) + { + this->con.swap(other.con); + std::swap(this->controlling_connection, other.controlling_connection); + } + + void swap(connection& c1, connection& c2) + { + c1.swap(c2); + } + + scoped_connection::scoped_connection(const connection& other) : + connection(other), + released(false) + { + } + + scoped_connection::scoped_connection(const scoped_connection& other) : + connection(other), + released(other.released) + { + } + + scoped_connection::~scoped_connection() + { + if (!released) { + this->disconnect(); + } + } + + connection scoped_connection::release() + { + released = true; + return *this; + } + + void scoped_connection::swap(scoped_connection& other) + { + this->connection::swap(other); + bool other_released = other.released; + other.released = this->released; + this->released = other_released; + } + + void swap(scoped_connection& c1, scoped_connection& c2) + { + c1.swap(c2); + } + + scoped_connection& + scoped_connection::operator=(const connection& other) + { + scoped_connection(other).swap(*this); + return *this; + } + + scoped_connection& + scoped_connection::operator=(const scoped_connection& other) + { + scoped_connection(other).swap(*this); + return *this; + } + + void + connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b) + { + assert(con.get() != 0); + con->bound_objects.push_back(b); + } + + + void connection::disconnect() const + { + if (this->connected()) { + // Make sure we have a reference to the basic_connection object, + // because 'this' may disappear + shared_ptr<detail::basic_connection> local_con = con; + + void (*signal_disconnect)(void*, void*) = local_con->signal_disconnect; + + // Note that this connection no longer exists + // Order is important here: we could get into an infinite loop if this + // isn't cleared before we try the disconnect. + local_con->signal_disconnect = 0; + + // Disconnect signal + signal_disconnect(local_con->signal, local_con->signal_data); + + // Disconnect all bound objects + typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator; + for (iterator i = local_con->bound_objects.begin(); + i != local_con->bound_objects.end(); ++i) { + assert(i->disconnect != 0); + i->disconnect(i->obj, i->data); + } + } + } + } // end namespace boost +} // end namespace boost + +#ifndef BOOST_MSVC +// Explicit instantiations to keep everything in the library +template class std::list<boost::BOOST_SIGNALS_NAMESPACE::detail::bound_object>; +#endif diff --git a/3rdParty/Boost/libs/signals/src/named_slot_map.cpp b/3rdParty/Boost/libs/signals/src/named_slot_map.cpp new file mode 100644 index 0000000..85a4bda --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/named_slot_map.cpp @@ -0,0 +1,134 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/detail/named_slot_map.hpp> +#include <cassert> +#include <map> +#include <list> +#include <typeinfo> + +namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail { + +typedef std::list<connection_slot_pair> group_list; +typedef group_list::iterator slot_pair_iterator; +typedef std::map<stored_group, group_list, compare_type> slot_container_type; +typedef slot_container_type::iterator group_iterator; +typedef slot_container_type::const_iterator const_group_iterator; + + +#if BOOST_WORKAROUND(_MSC_VER, <= 1500) +void named_slot_map_iterator::decrement() { assert(false); } +void named_slot_map_iterator::advance(difference_type) { assert(false); } +#endif + +named_slot_map::named_slot_map(const compare_type& compare) : groups(compare) +{ + clear(); +} + +void named_slot_map::clear() +{ + groups.clear(); + groups[stored_group(stored_group::sk_front)]; + groups[stored_group(stored_group::sk_back)]; + back = groups.end(); + --back; +} + +named_slot_map::iterator named_slot_map::begin() +{ + return named_slot_map::iterator(groups.begin(), groups.end()); +} + +named_slot_map::iterator named_slot_map::end() +{ + return named_slot_map::iterator(groups.end(), groups.end()); +} + +named_slot_map::iterator +named_slot_map::insert(const stored_group& name, const connection& con, + const any& slot, connect_position at) +{ + group_iterator group; + if (name.empty()) { + switch (at) { + case at_front: group = groups.begin(); break; + case at_back: group = back; break; + } + } else { + group = groups.find(name); + if (group == groups.end()) { + slot_container_type::value_type v(name, group_list()); + group = groups.insert(v).first; + } + } + iterator it; + it.group = group; + it.last_group = groups.end(); + + switch (at) { + case at_back: + group->second.push_back(connection_slot_pair(con, slot)); + it.slot_ = group->second.end(); + it.slot_assigned = true; + --(it.slot_); + break; + + case at_front: + group->second.push_front(connection_slot_pair(con, slot)); + it.slot_ = group->second.begin(); + it.slot_assigned = true; + break; + } + return it; +} + +void named_slot_map::disconnect(const stored_group& name) +{ + group_iterator group = groups.find(name); + if (group != groups.end()) { + slot_pair_iterator i = group->second.begin(); + while (i != group->second.end()) { + slot_pair_iterator next = i; + ++next; + i->first.disconnect(); + i = next; + } + groups.erase(group); + } +} + +void named_slot_map::erase(iterator pos) +{ + // Erase the slot + pos.slot_->first.disconnect(); + pos.group->second.erase(pos.slot_); +} + +void named_slot_map::remove_disconnected_slots() +{ + // Remove any disconnected slots + group_iterator g = groups.begin(); + while (g != groups.end()) { + slot_pair_iterator s = g->second.begin(); + while (s != g->second.end()) { + if (s->first.connected()) ++s; + else g->second.erase(s++); + } + + // Clear out empty groups + if (empty(g)) groups.erase(g++); + else ++g; + } +} + + +} } } diff --git a/3rdParty/Boost/libs/signals/src/signal_base.cpp b/3rdParty/Boost/libs/signals/src/signal_base.cpp new file mode 100644 index 0000000..759672d --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/signal_base.cpp @@ -0,0 +1,189 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/detail/signal_base.hpp> +#include <cassert> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + namespace detail { + signal_base_impl::signal_base_impl(const compare_type& comp, + const any& combiner) + : call_depth(0), + slots_(comp), + combiner_(combiner) + { + flags.delayed_disconnect = false; + flags.clearing = false; + } + + signal_base_impl::~signal_base_impl() + { + // Set the "clearing" flag to ignore extraneous disconnect requests, + // because all slots will be disconnected on destruction anyway. + flags.clearing = true; + } + + void signal_base_impl::disconnect_all_slots() + { + // Do nothing if we're already clearing the slot list + if (flags.clearing) + return; + + if (call_depth == 0) { + // Clearing the slot list will disconnect all slots automatically + temporarily_set_clearing set_clearing(this); + slots_.clear(); + } + else { + // We can't actually remove elements from the slot list because there + // are still iterators into the slot list that must not be + // invalidated by this operation. So just disconnect each slot + // without removing it from the slot list. When the call depth does + // reach zero, the call list will be cleared. + flags.delayed_disconnect = true; + temporarily_set_clearing set_clearing(this); + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + i->first.disconnect(); + } + } + } + + connection + signal_base_impl:: + connect_slot(const any& slot_, + const stored_group& name, + shared_ptr<slot_base::data_t> data, + connect_position at) + { + // Transfer the burden of ownership to a local, scoped + // connection. + data->watch_bound_objects.set_controlling(false); + scoped_connection safe_connection(data->watch_bound_objects); + + // Allocate storage for an iterator that will hold the point of + // insertion of the slot into the list. This is used to later remove + // the slot when it is disconnected. + std::auto_ptr<iterator> saved_iter(new iterator); + + // Add the slot to the list. + iterator pos = + slots_.insert(name, data->watch_bound_objects, slot_, at); + + // The assignment operation here absolutely must not throw, which + // intuitively makes sense (because any container's insert method + // becomes impossible to use in an exception-safe manner without this + // assumption), but doesn't appear to be mentioned in the standard. + *saved_iter = pos; + + // Fill out the connection object appropriately. None of these + // operations can throw + data->watch_bound_objects.get_connection()->signal = this; + data->watch_bound_objects.get_connection()->signal_data = + saved_iter.release(); + data->watch_bound_objects.get_connection()->signal_disconnect = + &signal_base_impl::slot_disconnected; + + // Make the copy of the connection in the list disconnect when it is + // destroyed. The local, scoped connection is then released + // because ownership has been transferred. + pos->first.set_controlling(); + return safe_connection.release(); + } + + bool signal_base_impl::empty() const + { + // Disconnected slots may still be in the list of slots if + // a) this is called while slots are being invoked (call_depth > 0) + // b) an exception was thrown in remove_disconnected_slots + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + if (i->first.connected()) + return false; + } + + return true; + } + + std::size_t signal_base_impl::num_slots() const + { + // Disconnected slots may still be in the list of slots if + // a) this is called while slots are being invoked (call_depth > 0) + // b) an exception was thrown in remove_disconnected_slots + std::size_t count = 0; + for (iterator i = slots_.begin(); i != slots_.end(); ++i) { + if (i->first.connected()) + ++count; + } + return count; + } + + void signal_base_impl::disconnect(const stored_group& group) + { slots_.disconnect(group); } + + void signal_base_impl::slot_disconnected(void* obj, void* data) + { + signal_base_impl* self = reinterpret_cast<signal_base_impl*>(obj); + + // We won't need the slot iterator after this + std::auto_ptr<iterator> slot(reinterpret_cast<iterator*>(data)); + + // If we're flags.clearing, we don't bother updating the list of slots + if (!self->flags.clearing) { + // If we're in a call, note the fact that a slot has been deleted so + // we can come back later to remove the iterator + if (self->call_depth > 0) { + self->flags.delayed_disconnect = true; + } + else { + // Just remove the slot now, it's safe + self->slots_.erase(*slot); + } + } + } + + void signal_base_impl::remove_disconnected_slots() const + { slots_.remove_disconnected_slots(); } + + call_notification:: + call_notification(const shared_ptr<signal_base_impl>& b) : + impl(b) + { + // A call will be made, so increment the call depth as a notification + impl->call_depth++; + } + + call_notification::~call_notification() + { + impl->call_depth--; + + // If the call depth is zero and we have some slots that have been + // disconnected during the calls, remove those slots from the list + if (impl->call_depth == 0 && + impl->flags.delayed_disconnect) { + impl->remove_disconnected_slots(); + impl->flags.delayed_disconnect = false; + } + } + + signal_base::signal_base(const compare_type& comp, const any& combiner) + : impl() + { + impl.reset(new signal_base_impl(comp, combiner)); + } + + signal_base::~signal_base() + { + } + + } // namespace detail + } // namespace BOOST_SIGNALS_NAMESPACE +} // namespace boost + diff --git a/3rdParty/Boost/libs/signals/src/slot.cpp b/3rdParty/Boost/libs/signals/src/slot.cpp new file mode 100644 index 0000000..7c296d6 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/slot.cpp @@ -0,0 +1,71 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/slot.hpp> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + namespace detail { + void slot_base::create_connection() + { + // Create a new connection object + basic_connection* con = new basic_connection(); + + /* nothrow */ { + // The signal portion isn't really necessary, except that we need a + // signal for the connection to be connected. + con->signal = static_cast<void*>(this); + con->signal_data = 0; + con->blocked_ = false ; + con->signal_disconnect = &bound_object_destructed; + } + + // This connection watches for destruction of bound objects. Note + // that the reset routine will delete con if an allocation throws + data->watch_bound_objects.reset(con); + + // We create a scoped connection, so that exceptions thrown while + // adding bound objects will cause a cleanup of the bound objects + // already connected. + scoped_connection safe_connection(data->watch_bound_objects); + + // Now notify each of the bound objects that they are connected to this + // slot. + for(std::vector<const trackable*>::iterator i = + data->bound_objects.begin(); + i != data->bound_objects.end(); ++i) { + // Notify the object that the slot is connecting to it + BOOST_SIGNALS_NAMESPACE::detail::bound_object binding; + (*i)->signal_connected(data->watch_bound_objects, binding); + + // This will notify the bound object that the connection just made + // should be disconnected if an exception is thrown before the + // end of this iteration + BOOST_SIGNALS_NAMESPACE::detail::auto_disconnect_bound_object + disconnector(binding); + + // Add the binding to the list of bindings for the connection + con->bound_objects.push_back(binding); + + // The connection object now knows about the bound object, so if an + // exception is thrown later the connection object will notify the + // bound object of the disconnection automatically + disconnector.release(); + } + + // No exceptions will be thrown past this point. + safe_connection.release(); + + data->watch_bound_objects.set_controlling(true); + } + } // end namespace detail + } // end namespace BOOST_SIGNALS_NAMESPACE +} // end namespace boost diff --git a/3rdParty/Boost/libs/signals/src/trackable.cpp b/3rdParty/Boost/libs/signals/src/trackable.cpp new file mode 100644 index 0000000..4f63586 --- /dev/null +++ b/3rdParty/Boost/libs/signals/src/trackable.cpp @@ -0,0 +1,59 @@ +// Boost.Signals library + +// Copyright Douglas Gregor 2001-2004. Use, modification and +// distribution is subject to the Boost Software License, Version +// 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// For more information, see http://www.boost.org + +#define BOOST_SIGNALS_SOURCE + +#include <boost/signals/trackable.hpp> +#include <algorithm> + +namespace boost { + namespace BOOST_SIGNALS_NAMESPACE { + void trackable::signal_disconnected(void* obj, void* data) + { + trackable* self = reinterpret_cast<trackable*>(obj); + connection_iterator* signal = + reinterpret_cast<connection_iterator*>(data); + + // If we're dying, don't bother erasing the connection from the list; + // it'll be gone anyway + if (!self->dying) { + self->connected_signals.erase(*signal); + } + + // This iterator pointer won't ever be used again + delete signal; + } + + void + trackable::signal_connected(connection c, + BOOST_SIGNALS_NAMESPACE::detail::bound_object& binding) const + { + // Insert the connection + connection_iterator pos = + connected_signals.insert(connected_signals.end(), c); + + // Make this copy of the object disconnect when destroyed + pos->set_controlling(); + + binding.obj = const_cast<void*>(reinterpret_cast<const void*>(this)); + binding.data = reinterpret_cast<void*>(new connection_iterator(pos)); + binding.disconnect = &signal_disconnected; + } + + trackable::~trackable() + { + dying = true; + } + } // end namespace BOOST_SIGNALS_NAMESPACE +} + +#ifndef BOOST_MSVC +// Explicit instantiations to keep in the library +template class std::list<boost::BOOST_SIGNALS_NAMESPACE::connection>; +#endif |