2
0
mirror of https://github.com/boostorg/signals.git synced 2026-01-19 04:42:10 +00:00

Added Boost.Signals library

[SVN r13964]
This commit is contained in:
Douglas Gregor
2002-05-17 15:28:22 +00:00
commit bce8c0037f
58 changed files with 6269 additions and 0 deletions

96
.gitattributes vendored Normal file
View File

@@ -0,0 +1,96 @@
* text=auto !eol svneol=native#text/plain
*.gitattributes text svneol=native#text/plain
# Scriptish formats
*.bat text svneol=native#text/plain
*.bsh text svneol=native#text/x-beanshell
*.cgi text svneol=native#text/plain
*.cmd text svneol=native#text/plain
*.js text svneol=native#text/javascript
*.php text svneol=native#text/x-php
*.pl text svneol=native#text/x-perl
*.pm text svneol=native#text/x-perl
*.py text svneol=native#text/x-python
*.sh eol=lf svneol=LF#text/x-sh
configure eol=lf svneol=LF#text/x-sh
# Image formats
*.bmp binary svneol=unset#image/bmp
*.gif binary svneol=unset#image/gif
*.ico binary svneol=unset#image/ico
*.jpeg binary svneol=unset#image/jpeg
*.jpg binary svneol=unset#image/jpeg
*.png binary svneol=unset#image/png
*.tif binary svneol=unset#image/tiff
*.tiff binary svneol=unset#image/tiff
*.svg text svneol=native#image/svg%2Bxml
# Data formats
*.pdf binary svneol=unset#application/pdf
*.avi binary svneol=unset#video/avi
*.doc binary svneol=unset#application/msword
*.dsp text svneol=crlf#text/plain
*.dsw text svneol=crlf#text/plain
*.eps binary svneol=unset#application/postscript
*.gz binary svneol=unset#application/gzip
*.mov binary svneol=unset#video/quicktime
*.mp3 binary svneol=unset#audio/mpeg
*.ppt binary svneol=unset#application/vnd.ms-powerpoint
*.ps binary svneol=unset#application/postscript
*.psd binary svneol=unset#application/photoshop
*.rdf binary svneol=unset#text/rdf
*.rss text svneol=unset#text/xml
*.rtf binary svneol=unset#text/rtf
*.sln text svneol=native#text/plain
*.swf binary svneol=unset#application/x-shockwave-flash
*.tgz binary svneol=unset#application/gzip
*.vcproj text svneol=native#text/xml
*.vcxproj text svneol=native#text/xml
*.vsprops text svneol=native#text/xml
*.wav binary svneol=unset#audio/wav
*.xls binary svneol=unset#application/vnd.ms-excel
*.zip binary svneol=unset#application/zip
# Text formats
.htaccess text svneol=native#text/plain
*.bbk text svneol=native#text/xml
*.cmake text svneol=native#text/plain
*.css text svneol=native#text/css
*.dtd text svneol=native#text/xml
*.htm text svneol=native#text/html
*.html text svneol=native#text/html
*.ini text svneol=native#text/plain
*.log text svneol=native#text/plain
*.mak text svneol=native#text/plain
*.qbk text svneol=native#text/plain
*.rst text svneol=native#text/plain
*.sql text svneol=native#text/x-sql
*.txt text svneol=native#text/plain
*.xhtml text svneol=native#text/xhtml%2Bxml
*.xml text svneol=native#text/xml
*.xsd text svneol=native#text/xml
*.xsl text svneol=native#text/xml
*.xslt text svneol=native#text/xml
*.xul text svneol=native#text/xul
*.yml text svneol=native#text/plain
boost-no-inspect text svneol=native#text/plain
CHANGES text svneol=native#text/plain
COPYING text svneol=native#text/plain
INSTALL text svneol=native#text/plain
Jamfile text svneol=native#text/plain
Jamroot text svneol=native#text/plain
Jamfile.v2 text svneol=native#text/plain
Jamrules text svneol=native#text/plain
Makefile* text svneol=native#text/plain
README text svneol=native#text/plain
TODO text svneol=native#text/plain
# Code formats
*.c text svneol=native#text/plain
*.cpp text svneol=native#text/plain
*.h text svneol=native#text/plain
*.hpp text svneol=native#text/plain
*.ipp text svneol=native#text/plain
*.tpp text svneol=native#text/plain
*.jam text svneol=native#text/plain
*.java text svneol=native#text/plain

24
build/Jamfile Normal file
View File

@@ -0,0 +1,24 @@
# (C) Copyright Douglas Gregor 2001-2.
# Permission to copy, use, modify, sell and
# distribute this software is granted provided this copyright notice appears
# in all copies. This software is provided "as is" without express or implied
# warranty, and with no claim as to its suitability for any purpose.
#
# Boost.Signals build and test Jamfile
# declare the location of this subproject relative to the root
subproject libs/signals/build ;
# Base names of the source files for libboost_signals
CPP_SOURCES =
trackable connection signal_base slot ;
dll boost_signals : ../src/$(CPP_SOURCES).cpp
: <include>$(BOOST_ROOT)
: debug release
;
lib boost_signals : ../src/$(CPP_SOURCES).cpp
: <include>$(BOOST_ROOT)
: debug release
;

174
doc/design.html Normal file
View File

@@ -0,0 +1,174 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals Design</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals Design</h1>
<p> This document describes the high-level design of the Boost.Signals
library. An additional document describes the <a
href="design_rationale.html">design rationale</a>.
<h2>Table of Contents</h2>
<ul>
<li><a href="#type_erasure">Type Erasure</a></li>
<li><a href="#connection"><code>connection</code> class</a></li>
<li><a href="#slot_call_iterator">Slot Call Iterator</a></li>
<li><a href="#visit_each"><code>visit_each</code> function template</a></li>
</ul>
<h2><a name="type_erasure">Type Erasure</a></h2>
<p> Type erasure is used extensively within the Boost.Signals library
to reduce the amount of code generated by template
instantiation. Each signal must manage a list of slots and their
associated connections, along with a <code>std::map</code> to map from
slot names to their associated connections. However, instantiating
this map for every token type, and perhaps within each translation
unit (for some popular template instantiation strategies) increase
compile time overhead and space overhead.
<p> To combat this so-called "template bloat", we use <a
href="../../function/index.html">Boost.Function</a> and <a
href="../../any/index.html">Boost.Any</a> to store unknown types and
operations. Then, all of the code for handling the list of slots and
the mapping from named slots to connections is factored into the class
<a
href="../../../boost/signals/signal_base.hpp"><code>signal_base</code></a>
that deals exclusively with the <code>any</code> and
<code>function</code> objects, hiding the actual implementations using
the well-known pimpl idiom. The actual <a
href="reference/signalN.html"><code>signal<em>N</em></code></a> class
templates deal only with code that will change depending on the number
of arguments or which is inherently template-dependent (such as
connection).
<h2><a name="connection"><code>connection</code> class</a></h2>
<p> The <code>connection</code> class is central to the behavior of
the Boost.Signals library. It is the only entity within the
Boost.Signals system that has knowledge of all objects that are
associated by a given connection. To be specific, the
<code>connection</code> class itself is merely a thin wrapper over a
<a href="../../libs/smart_ptr/index.htm"><code>shared_ptr</code></a>
to a <code>basic_connection</code> object.
<p> <code>connection</code> objects are stored by all participants in
the Signals system: each <a
href="reference/trackable.html"><code>trackable</code></a> object
contains a list of <code>connection</code> objects describing all
connections it is a part of; similarly, all signals contain a set of
pairs that define a slot. The pairs consist of a slot function object
(generally a <a href="../../function/index.html">Boost.Function</a>
object) and a <code>connection</code> object (that will disconnect on
destruction). Finally, the mapping from slot groups to slots is based
on the key value in a <code>std::multimap</code> (the stored data in
the <code>std::multimap</code> is the slot pair).
<h2><a name="slot_call_iterator">Slot Call Iterator</a></h2>
<p> The slot call iterator is conceptually a stack of iterator
adaptors that modify the behavior of the underlying iterator
through the list of slots. The following table describes the
type and behavior of each iterator adaptor required. Note that
this is only a conceptual model: the implementation collapses
all these layers into a single iterator adaptor because several
popular compilers failed to compile the implementation of the
conceptual model.
<table border=1>
<tr>
<th><center>Iterator Adaptor</center></th>
<th>Purpose</th>
</tr>
<tr>
<td><center>Slot List Iterator</center></td>
<td>An iterator through the list of slots connected to a signal. The
<code>value_type</code> of this iterator will be
<code>std::pair&lt;any, connection&gt;</code>, where the
<code>any</code> contains an instance of the slot function
type.</td>
</tr>
<tr>
<td><center>Filter Iterator Adaptor</center></td>
<td>This filtering iterator adaptor filters out slots that have been
disconnected, so we never see a disconnected slot in later
stages.</td>
</tr>
<tr>
<td><center>Projection Iterator Adaptor</center></td>
<td>The projection iterator adaptor returns a reference to the first
member of the pair that constitutes a connected slot
(e.g., just the <code>boost::any</code> object that holds
the slot function).</td>
</tr>
<tr>
<td><center>Transform Iterator Adaptor</center></td>
<td>This transform iterator adaptor performs an
<code>any_cast</code> to extract a reference to the slot
function with the appropriate slot function type.</td>
</tr>
<tr>
<td><center>Transform Iterator Adaptor</center></td>
<td>This transform iterator adaptor calls the function object
returned by dereferencing the underlying iterator with
the set of arguments given to the signal itself, and
returns the result of that slot call.</td>
</tr>
<tr>
<td><center>Input Caching Iterator Adaptor</center></td>
<td>This iterator adaptor caches the result of dereferencing the
underlying iterator. Therefore, dereferencing this
iterator multiple times will only result in the underlying
iterator being dereferenced once; thus, a slot can only be
called once but its result can be used multiple times.</td>
</tr>
<tr><td colspan=2><center>Slot Call Iterator</center></td</tr>
</table>
<h2><a name="visit_each"><code>visit_each</code> function template</a></h2>
<p> The <a href="reference/visit_each.html"><code>visit_each</code></a>
function template is a mechanism for discovering objects that
are stored within another object. Function template
<code>visit_each</code> takes three arguments: an object to
explore, a visitor function object that is invoked with each
subobject, and the <code>int</code> 0. </p>
<p> The third parameter is merely a temporary solution to the
widespread lack of proper function template partial
ordering. The primary <code>visit_each</code> function template
specifies this third parameter type to be <code>long</code>,
whereas any user specializations must specify their third
parameter to be of type <code>int</code>. Thus, even though a
broken compiler cannot tell the ordering between, e.g., a
match against a parameter <code>T</code> and a parameter
<code>A&lt;T&gt;</code>, it can determine that the conversion
from the integer 0 to <code>int</code> is better than the
conversion to <code>long</code>. The ordering determined by this
conversion thus achieves partial ordering of the function
templates in a limited, but successful, way. The following
example illustrates the use of this technique:</p>
<pre>
template&lt;typename&gt; class A {};
template&lt;typename T&gt; void foo(T, long);
template&lt;typename T&gt; void foo(A&lt;T&gt;, int);
A&lt;T&gt; at;
foo(at, 0);
</pre>
<p> In this example, we assume that our compiler can not tell that
<code>A&lt;T&gt;</code> is a better match than <code>T</code>,
and therefore assume that the function templates cannot be
ordered based on that parameter. Then the conversion from 0 to
<code>int</code> is better than the conversion from 0 to
<code>long</code>, and the second function template is chosen. </p>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 28 00:23:34 EST 2002
<!-- hhmts end -->
</body>
</html>

374
doc/design_rationale.html Normal file
View File

@@ -0,0 +1,374 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals Design Rationale</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals Design Rationale</h1>
<p> This document describes the rationale behind some of the major
design decisions made for the Boost.Signals library.
<h2>Table of Contents</h2>
<ul>
<li>Design Decisions and Rationale
<ul>
<li><a href="#slotdef">Choice of Slot Definitions</a></li>
<li><a href="#user_connect">User-level Connection Management</a></li>
<li><a href="#combiners">Combiner Interface</a></li>
<li><a href="#plus_equals">Connection Interfaces: += operator</a></li>
<li><a href="#trackable"><code>trackable</code> rationale</a></li>
</ul></li>
<li>Comparisons with other signals &amp; slots designs
<ul>
<li><a href="#libsigc">libsigc++</a></li>
<li><a href="#delegates">.NET delegates</a></li>
</ul></li>
</ul>
<hr><h2><a name="slotdef">Choice of Slot Definitions</a></h2>
<p> The definition of a slot differs amongst signals and slots
libraries. Within Boost.Signals, a slot is defined in a very loose
manner: it can be any function object that is callable given
parameters of the types specified by the signal, and whose return
value is convertible to the result type expected by the
signal. However, alternative definitions have associated pros and
cons that were considered prior to the construction of
Boost.Signals.
<ul>
<li><b>Slots derive from a specific base class</b>: generally a
scheme such as this will require all user-defined slots to derive
from some library-specified <code>Slot</code> abstract class
that defines a virtual function calling the slot. Adaptors can be
used to convert a definition such as this to a definition similar
to that used by Boost.Signals, but in this case the original
specification ties the implementation to the use of virtual
functions internally. This approach does have the benefit of
simplicity of implementation and user interface, from an
object-oriented perspective.</li>
<li><b>Slots constructed from a set of primitives</b>: in this
scheme the slot can have a limited set of types (often derived
from a common abstract base class) that are constructed from some
library-defined set of primitives that often include conversions
from free function pointers and member function pointers, and a
limited set of binding capabilities. Such an approach is
reasonably simple and cover most common cases, but it does not
allow a large degree of flexibility in slot
construction. Libraries for function object composition have
become quite advanced and it is out of the scope of a signals and
slots library to encorporate such enhancements. Thus Boost.Signals
does not include argument binding or function object composition
primitives, but instead uses a set of well-defined interfaces to
discover information about the composition of arbitrary function
objects.</li>
</ul>
<p> Users not satisfied with the slot definition choice may opt to
replace the default slot function type with an alternative that
meets their specific needs.
<h2><a name="user_connect">User-level Connection Management</a></h2>
<p> Users need to have fine control over the connection of signals
to slots and their eventual disconnection. The approach taken by
Boost.Signals is to return a <a
href="reference/connection.html"><code>connection</code></a> object
that enables connected/disconnected query, manual disconnection, and
an automatic disconnection on destruction mode. Some other possible
interfaces include:
<ul>
<li><b>Pass slot to disconnect</b>: in this interface model, the
disconnection of a slot connected with
<code>sig.connect(slot)</code> is performed via
<code>sig.disconnect(slot)</code>. Internally, a linear search
using slot comparison is performed and the slot, if found, is
removed from the list. Unfortunately, querying connectedness will
generally also end up as linear-time operations. This model also
fails for implementation reasons when slots become more complex
than simple function pointers, member function pointers, and a
limited set of compositions and argument binders it is tough to
rely on comparison of function objects because arbitrary function
objects are not comparable.</li>
<li><b>Pass a token to disconnect</b>: this approach identifies
slots with a token that is easily comparable (e.g., a string),
enabling slots to be arbitrary function objects. While this
approach is essentially equivalent to the approach taken by
Boost.Signals, it is possibly more error-prone for several
reasons:
<ul>
<li>Connections and disconnections must be paired, so the
problem becomes similar to the problems incurred when pairing
<code>new</code> and <code>delete</code> for dynamic memory
allocation. While errors of this sort would not be catastrophic
for a signals and slots implementation, their detection is
generally nontrivial.</li>
<li>Tokens must be unique, otherwise two slots will have the
same name and will be indistinguishable. In environments where
many connections will be made dynamically, name generation
becomes an additional task for the user. Uniqueness of tokens
also results in an additional failure mode when attempting to
connect a slot using a token that has already been used. </li>
<li>More parameterization would be required, because the token
type must be user-defined. Additional parameterization steepens
the learning curver and overcomplicates a simple interface.</li>
</ul>
<p> This type of interface is supported in Boost.Signals via the
named connections mechanism. It augments the <a
href="reference/connection.html"><code>connection</code></a>
object-based connection management scheme.
</li>
</ul>
<h2><a name="combiners">Combiner Interface</a></h2>
<p> The Combiner interface was chosen to mimic a call to an
algorithm in the C++ standard library. It is felt that by viewing
slot call results as merely a sequence of values accessed by input
iterators, the combiner interface would be most natural to a
proficient C++ programmer. Competing interface design generally
required the combiners to be constructed to conform to an interface
that would be customized for (and limited to) the Signals
library. While these interfaces are generally enable more
straighforward implementation of the signals &amp; slots libraries,
the combiners are unfortunately not reusable (either in other
signals &amp; slots libraries or within other generic algorithms),
and the learning curve is steepened slightly to learn the specific
combiner interface.
<p> The Signals formulation of combiners is based on the combiner
using the "pull" mode of communication, instead of the more complex
"push" mechanism. With a "pull" mechanism, the combiner's state can
be kept on the stack and in the program counter, because whenever
new data is required (i.e., calling the next slot to retrieve its
return value), there is a simple interface to retrieve that data
immediately and without returning from the combiner's code. Contrast
this with the "push" mechanism, where the combiner must keep all
state in class members because the combiner's routines will be
invoked for each signal called. Compare, for example, a combiner
that returns the maximum element from calling the slots. If the
maximum element ever exceeds 100, no more slots are to be
called.
<table border=1>
<tr>
<th>Pull</th>
<th>Push</th>
</tr>
<tr>
<td>
<pre>
struct pull_max {
typedef int result_type;
template&lt;typename InputIterator&gt;
result_type operator()(InputIterator first,
InputIterator last)
{
if (first == last)
throw std::runtime_error("Empty!");
int max_value = *first++;
while(first != last && *first &lt;= 100) {
if (*first &gt; max_value)
max_value = *first;
++first;
}
return max_value;
}
};
</pre>
</td>
<td>
<pre>
struct push_max {
typedef int result_type;
push_max() : max_value(), got_first(false) {}
// returns false when we want to stop
bool operator()(int result) {
if (result &gt; 100)
return false;
if (!got_first) {
got_first = true;
max_value = result;
return true;
}
if (result &gt; max_value)
max_value = result;
return true;
}
int get_value() const
{
if (!got_first)
throw std::runtime_error("Empty!");
return max_value;
}
private:
int max_value;
bool got_first;
};
</pre>
</td>
</tr>
</table>
<p>There are several points to note in these examples. The "pull"
version is a reusable function object that is based on an input
iterator sequence with an integer <code>value_type</code>, and is
very straightforward in design. The "push" model, on the other hand,
relies on an interface specific to the caller and is generally
reusable. It also requires extra state values to determine, for
instance, if any elements have been received. Though code quality
and ease-of-use is generally subjective, the "pull" model is clearly
shorter and more reusable and will often be construed as easier to
write and understand, even outside the context of a signals &amp;
slots library.
<p> The cost of the "pull" combiner interface is paid in the
implementation of the Signals library itself. To correctly handle
slot disconnections during calls (e.g., when the dereference
operator is invoked), one must construct the iterator to skip over
disconnected slots. Additionally, the iterator must carry with it
the set of arguments to pass to each slot (although a
reference to a structure containing those arguments suffices), and
must cache the result of calling the slot so that multiple
dereferences don't result in multiple calls. This apparently
requires a large degree of overhead, though if one considers the
entire process of invoking slots one sees that the overhead is
nearly equivalent to that in the "push" model, but we have inverted
the control structures to make iteration and dereference complex
(instead of making combiner state-finding complex).
<h2><a name="plus_equals">Connection Interfaces: += operator</a></h2>
<p> Boost.Signals supports a connection syntax with the form
<code>sig.connect(slot)</code>, but a more terse syntax <code>sig +=
slot</code> has been suggested (and has been used by other signals
&amp; slots implementations). There are several reasons as to why
this syntax has been rejected:
<ul>
<li><b>It's unnecessary</b>: the connection syntax supplied by
Boost.Signals is no less powerful that than supplied by the
signal. The savings in typing (<code>connect()</code>
vs. <code>+=</code>) is essentially negligible. Furthemore, one
could argue that calling <code>connect()</code> is more readable
than an overload of <code>+=</code>.
<li><b>Ambiguous return type</b>:
there is an ambiguity concerning the return value of the
<code>+=</code> operation: should it be a reference to the signal
itself, to enable <code>sig += slot1 += slot2</code>, or should it
return a <code><a
href="reference/connection.html">connection</a></code> for the
newly-created signal/slot connection?</li>
<li><b>Gateway to operators -=, +</b>: when one has added a
connection operator <code>+=</code>, it seems natural to have a
disconnection operator <code>-=</code>. However, this presents
problems when the library allows arbitrary function objects to
implicitly become slots, because slots are no longer comparable
(see the discussion on this topic in <a
href="#user_connect">User-level Connection Management</a>).
<p> The second obvious addition when one has
<code>operator+=</code> would be to add a <code>+</code> operator
that supports addition of multiple slots, followed by assignment
to a signal. However, this would require implementing
<code>+</code> such that it can accept any two function objects,
which is technically infeasible.
</ul>
<h2><a name="trackable"><code>trackable</code> rationale</a></h2>
<p> The <a href="doc/trackable.html"><code>trackable</code></a>
class is the primary user interface to automatic connection
lifetime management, and its design affects users directly. Two
issues stick out most: the odd copying behavior of
<code>trackable</code>, and the limitation requiring users to
derive from <code>trackable</code> to create types that can
participate in automatic connection management.
<h3><code>trackable</code> copying behavior</h3>
<p> The copying behavior of <code>trackable</code> is essentially
that <code>trackable</code> subobjects are never copied;
instead, the copy operation is merely a no-op. To understand
this, we look at the nature of a signal-slot connection and note
that the connection is based on the entities that are being
connected; when one of the entities is destroyed, the connection
is destroyed. Therefore, when a <code>trackable</code> subobject
is copied, we cannot copy the connections because the
connections don't refer to the target entity - they refer to the
source entity. This reason is dual to the reason signals are
noncopyable: the slots connected to them are connected to that
particular signal, not the data contained in the signal.
<h3>Why derivation from <code>trackable</code>?</h3>
<p> For <code>trackable</code> to work properly, there are two
constraints:
<ul>
<li><code>trackable</code> must have storage space to keep
track of all connections made to this object.</li>
<li><code>trackable</code> must be notified when the object is
being destructed so that it can disconnect its
connections.</li>
</ul>
Clearly, deriving from <code>trackable</code> meets these two
guidelines. We have not yet found a superior solution.
<hr><h2><a name="libsigc">libsigc++</a></h2>
<p> <a href="http://libsigc.sourceforge.net">libsigc++</a> is a C++ signals
&amp; slots library that originally started as part of an initiative
to wrap the C interfaces to <a href="http://www.gtk.org">GTK</a>
libraries in C++, and has grown to be a separate library maintained
by Karl Nelson. There are many similarities between libsigc++ and
Boost.Signals, and indeed Boost.Signals was strongly influenced by
Karl Nelson and libsigc++. A cursory inspection of each library will
find a similar syntax for the construction of signals and in the use
of connections and automatic connection lifetime management. There
are some major differences in design that separate these libraries:
<ul>
<li><b>Slot definitions</b>: slots in libsigc++ are created using
a set of primitives defined by the library. These primitives allow
binding of objects (as part of the library), explicit
adaptation from the argument and return types of the signal to the
argument and return types of the slot (libsigc++ is, by default,
more strict about types than Boost.Signals). A discussion of this
approach with a comparison against the approach taken by
Boost.Signals is given in
<a href="#slotdef">Choice of Slot Definitions</a>.</li>
<li><b>Combiner/Marshaller interface</b>: the equivalent to
Boost.Signals combiners in libsigc++ are the
marshallers. Marshallers are similar to the "push" interface
described in <a href="#combiners">Combiner Interface</a>, and a
proper treatment of the topic is given there.</li>
</ul>
<h2><a name="delegates">.NET delegates</a></h2>
<p> <a href="http://www.microsoft.com">Microsoft</a> has introduced
the .NET Framework and an associated set of languages and language
extensions, one of which is the delgate. Delegates are similar
to signals and slots, but they are more limited than most C++
signals and slots implemetations in that they:
<ul>
<li>Require exact type matches between a delegate and what it is
calling</li>
<li>Do not allow return types</li>
<li>Must call a method with <code>this</code> already bound</li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 14 21:07:10 EST 2002
<!-- hhmts end -->
</body>
</html>

30
doc/faq.html Normal file
View File

@@ -0,0 +1,30 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals Frequently Asked Questions</title>
</head>
<body>
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals Frequently Asked Questions</h1>
<h2>Q: Don't noncopyable signal semantics mean that a class with a signal member will be noncopyable as well?</h2>
<p> No. The compiler will not be able to generate a copy
constructor or copy assignment operator for your class if it has
a signal as a member, but you are free to write your own copy
constructor and/or copy assignment operator. Just don't try to
copy the signal.</p>
<h2>Q: Is Boost.Signals thread-safe?</h2>
<p> No. Using Boost.Signals in a multithreaded concept is very
dangerous, and it is very likely that the results will be less
than satisfying. Boost.Signals will support thread safety in the
future.</p>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu"></a></address>
<!-- Created: Wed Feb 27 23:53:03 EST 2002 -->
<!-- hhmts start -->
Last modified: Thu Feb 28 00:05:16 EST 2002
<!-- hhmts end -->
</body>
</html>

179
doc/history.html Normal file
View File

@@ -0,0 +1,179 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals Revision History</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals Revision History</h1>
<table border=1>
<tr>
<th>Date</th>
<th>Change Summary</th>
</tr>
<tr>
<td>2002-04-10</td>
<td>
<ul>
<li>Added <a href="faq.html">Frequently Asked Questions</a> document.</li>
<li>Added <code>visit_each</code> discussion to the
<a href="design.html">design document</a>.</li>
<li>Made <code>deletion_test</code> actually perform tests.</li>
<li>Fixed <code>slot_call_iterator</code> behavior when a slot
deletes the next slot after incrementing the
slot call iterator to that slot (i.e., when using the
<code>*first++</code> syntax) <em>again</em>.</li>
<li>Moved <code>last_value</code> into the top-level Boost
directory and removed dependencies on Signals
library.</li>
<li>Moved implementation detail headers
<code>signal_base.hpp</code>,
<code>signals_common.hpp</code> and
<code>slot_call_iterator.hpp</code> into
<code>boost/signals/detail</code>.</li>
<li>Moved <code>trackable</code> and <code>connection</code>
classes into namespace
<code>boost::signals</code>.</li>
<li>Moved implementation details from namespace
<code>detail::signals</code> to namespace
<code>signals::detail</code>.</li>
<li>Fixed <code>signal<em>N</em>.hpp</code> headers to use types
<code>T1, T2, ..., T<em>N</em></code> instead of
<code>T0, T1, ..., T<em>N-1</em></code>. Added
appropriate typedefs <code>argument_type</code>,
<code>first_argument_type</code> and
<code>second_argument_type</code>. </li>
<li>Minor exception safety updates in constructors.</li>
<li>Removed "controlling" connections from the public
interface. Added the <code>scoped_connection</code>
class to pick up the slack, but with more obvious
semantics.</li>
<li>Slot names have become connection groups. Slot call ordering
is now dependent on the connection group ordering, with
ungrouped slots being called last.</li>
<li>Added testcase for slot call ordering.</li>
</ul>
</td>
</tr>
<tr>
<td>2002-02-14</td>
<td>
<ul>
<li>Make sure all <code>shared_ptr</code> copies are performed
only when complete types are available.</li>
<li>Added test for dead slots.</li>
<li>Removed use of <code>scoped_ptr</code> (it made Borland C++
unhappy).</li>
<li>Jamfile updates for the latest Jam changes in CVS.</li>
<li>Validated HTML.</li>
</ul>
</td>
</tr>
<tr>
<td>2002-01-19</td>
<td>
<ul>
<li>Refactored slot connection into <code>signal_base</code>.</li>
<li>Revisited exception safety in slot connection routines.</li>
<li>Updated <code>slot_call_iterator</code> to properly cache
values even when there are multiple input iterators.</li>
<li>Changed <code>signal_base</code> to use the handle/body idiom
via a <code>shared_ptr</code>. This enables safe recursive
deletion.</li>
<li>Added a comprehensive connection-tracking test system based on
the Boost graph library. See <a href="../test/random_signal_system.cpp"><code>random_signal_system.cpp</code></a>.</li>
<li>Refactored slot class into a <code>slot_base</code> class;
connection management code moved into <code>slot.cpp</code>.</li>
</ul>
</td>
</tr>
<tr>
<td>2001-12-28</td>
<td>
<ul>
<li>Added <code>slot</code> class template so that slots may be
passed as arguments to non-template functions. (Karl
Nelson)</li>
<li>Updated <code>signal<em>N</em></code> class templates to use the
new <code>slot</code> class template.</li>
<li>Tutorial updated to contain information about
<code>slot</code>.</li>
<li><code>visit_each</code> documentation added. (Karl
Nelson)</li>
<li>More Borland C++ fixes.</li>
</ul>
</td>
</tr>
<tr>
<td>2001-12-24</td>
<td>
<ul>
<li>Update to match <code>visit_each</code> framework supported
by Boost.Bind</li>
<li>Signals can be connected to other signals directly.</li>
<li>Signals can be connected to references to slot function
objects (function objects are then not copied).</li>
<li>Added <code>arg<em>I</em>_type</code> types to signal
classes, and cleaned up the corresponding
documentation (thanks to Bill Kempf).</li>
<li>Document noncopyable requirement (thanks to Bill
Kempf).</li>
<li>"Bindable" changed to "Trackable" (thanks to Peter Dimov).</li>
<li>Added named slot connections (thanks for Peter Dimov for the suggestion, and Brad King for the push toward a small implementation).</li>
<li>Trackable rationale documentation.</li>
<li>Explicitly instantiate what Signals needs within the non-template source.</li>
<li>Editorial fixes in the tutorial.</li>
<li>Added examples directory.</li>
<li>Added <code>SlotFunction</code> template parameter to specify the type of object to hold the slot function objects (suggested by Peter Dimov).</li>
<li>Documentation updates for <code>signal<em>N</em></code> classes.</li>
<li>Link to all header files within the documentation for those header files.</li>
<li>Moved all headers except <code>signal.hpp</code> into signals subdirectory.</li>
<li><code>return_last_value</code> renamed to <code>last_value</code>.</li>
<li>Proper documentation for <code>last_value</code> class.</li>
</ul>
</td>
</tr>
<tr>
<td>2001-11-25</td>
<td>
<ul>
<li>Fixes for MSVC and Borland C++.</li>
<li>Added Documentation: design rationale &amp; comparisons with other signals &amp; slots implementations.</li>
<li>Signal connection now meets the strong exception guarantee.</li>
<li>Jamfile fixes for building the "bindable.cpp" test</li>
<li>Combined transform_iterator, skip_if_iterator, and
input_caching_iterator into a single
slot_call_iterator to reduce template depth and
compiler confusion.</li>
</ul>
</td>
</tr>
<tr>
<td>2001-11-18</td>
<td>
<ul>
<li>Refactoring of signal connection management code.</li>
<li>Exception safety greatly improved (it is now safe for slots to throw
exceptions)</li>
<li>Uses Boost.Build</li>
<li>Documentation (reference and tutorial)</li>
<li>Updated to work with newer versions of Iterator
Adaptors</li>
</ul>
</td>
</tr>
<tr>
<td>2001-07-02</td>
<td>Initial prototype</td>
</tr>
</table>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu"></a></address>
<!-- Created: Fri Dec 14 19:03:54 EST 2001 -->
<!-- hhmts start -->
Last modified: Wed Apr 10 19:47:13 EDT 2002
<!-- hhmts end -->
</body>
</html>

40
doc/index.html Normal file
View File

@@ -0,0 +1,40 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals</h1>
<p> The Boost.Signals library is an implementation of a managed signals and slots system. Signals represent callbacks with multiple targets, and are also called publishers or events in similar systems. Signals are connected to some set of slots, which are callback receivers (also called event targets or subscribers), which are called when the signal is "emitted."
<p> Signals and slots are managed, in that signals and slots (or, more properly, objects that occur as part of the slots) track all connections and are capable of automatically disconnecting signal/slot connections when either is destroyed. This enables the user to make signal/slot connections without expending a great effort to manage the lifetimes of those connections with regard to the lifetimes of all objects involved.
<p> When signals are connected to multiple slots, there is a question regarding the relationship between the return values of the slots and the return value of the signals. Boost.Signals allows the user to specify the manner in which multiple return values are combined.
<h2>Table of Contents</h2>
<ul>
<li><a href="tutorial.html">Tutorial</a></li>
<li>Reference
<ul>
<li> Class template <a href="reference/signal.html"><code>signal</code></a></li>
<li> Class templates <a href="reference/signalN.html"><code>signal<em>N</em></code></a></li>
<li> Class template <a href="reference/slot.html"><code>slot</code></a>
</li>
<li> Class <a href="reference/trackable.html"><code>trackable</code></a></li>
<li> Class <a href="reference/connection.html"><code>connection</code></a></li>
<li> Class template <a href="reference/last_value.html"><code>last_value</code></a></li>
<li> Function template <a href="reference/visit_each.html"><code>visit_each</code></a></li>
</ul></li>
<li><a href="faq.html">Frequently Asked Questions</a></li>
<li><a href="design.html">Design of Boost.Signals</a></li>
<li><a href="design_rationale.html">Design Rationale and Comparisons with Other Signal/Slot Implementations</a></li>
<li><a href="history.html">Revision History</a>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 28 00:05:38 EST 2002
<!-- hhmts end -->
</body>
</html>

View File

@@ -0,0 +1,208 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: Header &lt;boost/signals/connection.hpp&gt;</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: Header <code>&lt;<a href="../../../../boost/signals/connection.hpp">boost/signals/connection.hpp</a>&gt;</code></h1>
<h2>Header <code>&lt;<a href="../../../../boost/signals/connection.hpp">boost/signals/connection.hpp</a>&gt;</code> synopsis</h2>
<pre>
<b>namespace</b> boost {
<b>namespace</b> signals {
class <a href="#connection_class">connection</a>;
class <a href="#scoped_connection_class">scoped_connection</a>;
<a href="#swap_free"><b>void</b> swap(connection&amp, connection&amp;)</a>;
<a href="#scoped_swap_free"><b>void</b> swap(scoped_connection&amp, scoped_connection&amp;)</a>;
}
}
</pre>
<a name="connection_class"><h2>Class <code>connection</code> synopsis</h2></a>
<p>The <code>connection</code> class represents a connection between a <a href="Signal.html">Signal</a> and a <a href="Slot.html">Slot</a>. It is a lightweight object that has the ability to query whether the signal and slot are currently connected, and to disconnect the signal and slot. It is always safe to query or disconnect a <code>connection</code>.
<pre>
<b>namespace</b> boost {
<b>namespace</b> signals {
<b>class</b> connection : <em>// Class connection is <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a> and <a href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a></em>
<b>private</b> less_than_comparable1&lt;connection&gt;, <em>// Exposition only.</em>
<b>private</b> equality_comparable1&lt;connection&gt;<em>// Exposition only.</em>
{
<b>public</b>:
<a href="#default_constructor">connection()</a>;
<a href="#copy_constructor">connection(<b>const</b> connection&amp;)</a>;
<a href="#destructor">~connection()</a>;
<a href="#disconnect"><b>void</b> disconnect() <b>const</b></a>;
<a href="#connected"><b>bool</b> connected() <b>const</b></a>;
<a href="#copy_assignment">connection& <b>operator=</b>(<b>const</b> connection&amp;)</a>;
<a href="#swap_member"><b>void</b> swap(connection&amp;)</a>;
<a href="#equality"><b>bool</b> <b>operator==</b>(<b>const</b> connection& other) <b>const</b></a>;
<a href="#less_than"><b>bool</b> <b>operator&lt;</b>(<b>const</b> connection& other) <b>const</b></a>;
};
}
}
</pre>
<h2>Class <code>connection</code> members</h2>
<hr><h3>Constructors</h3>
<p><a name="default_constructor"><code>connection();</code></a>
<ul>
<li><b>Effects</b>: Sets the currently represented connection to the NULL connection.</li>
<li><b>Postconditions</b>: <code>!<b>this</b>-&gt;connected()</code>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="copy_constructor"><code>connection(<b>const</b> connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>this</code> references the connection referenced by <code>other</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr><h3>Destructor</h3>
<p><a name="destructor">~<code>connection();</code></a>
<ul>
<li><b>Effects</b>: none.</li>
</ul>
<hr><h3>Connection Management</h3>
<p><a name="disconnect"><code><b>void</b> disconnect() <b>const</b>;</code></a>
<ul>
<li><b>Effects</b>: if <code><b>this-&gt;</b>is_connected()</code>, disconnects the signal and slot referenced by <code>this</code>; otherwise, this operation is a no-op.</li>
<li><b>Postconditions</b>: <code><b>!this</b>-&gt;is_connected()</code></li>
</ul>
<p><a name="connected"><code><b>bool</b> connected() <b>const</b>;</code></a>
<ul>
<li><b>Returns</b>: <code><b>true</b></code> if <code>this</code> references a non-NULL connection that is still active (connected), and <code><b>false</b></code> otherwise.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr><h3>Assignment and Swap</h3>
<p><a name="copy_assignment"><code>connection&amp; <b>operator=</b>(<b>const</b> connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>connection(other).swap(*<b>this</b>);</code>
<li><b>Returns</b>: <code>*<b>this</b></code></li>
</ul>
<p><a name="swap_member"><code><b>void</b> swap(connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: swaps the connections referenced in <code><b>this</b></code> and <code>other</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr><h3>Comparison</h3>
<p><a name="equality"><code><b>bool</b> <b>operator==</b>(<b>const</b> connection& other) <b>const</b>;</code></a>
<ul>
<li><b>Returns</b>: true if <code><b>this</b></code> and <code>other</code> reference the same connection or both reference the NULL connection, and <code><b>false</b></code> otherwise.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="less_than"><code><b>bool</b> <b>operator&lt;</b>(<b>const</b> connection& other) <b>const</b>;</code></a>
<ul>
<li><b>Returns</b>: <code><b>true</b></code> if the connection referenced by <code><b>this</b></code> precedes the connection referenced by <code>other</code> based on some implementation-defined ordering, and <code><b>false</b></code> otherwise. </li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<a name="scoped_connection_class"><h2>Class <code>scoped_connection</code> synopsis</h2></a>
<p>The <code>scoped_connection</code> class is a connection that will
be automatically disconnected when the <code>scoped_connection</code>
instance is destructed.
<pre>
<b>namespace</b> boost {
<b>namespace</b> signals {
<b>class</b> scoped_connection : <b>public</b> connection
{
<b>public</b>:
<a href="#scoped_default_constructor">scoped_connection()</a>;
<a href="#scoped_copy_constructor">scoped_connection(<b>const</b> scoped_connection&amp;)</a>;
<a href="#scoped_copy_connection_constructor">scoped_connection(<b>const</b> connection&amp;)</a>;
<a href="#scoped_destructor">~scoped_connection()</a>;
<a href="#scoped_copy_assignment">connection& <b>operator=</b>(<b>const</b> scoped_connection&amp;)</a>;
<a href="#scoped_copy_connection_assignment">connection& <b>operator=</b>(<b>const</b> connection&amp;)</a>;
<a href="#scoped_swap_member"><b>void</b> swap(connection&amp;)</a>;
};
}
}
</pre>
<h2>Class <code>scoped_connection</code> members</h2>
<hr><h3>Constructors</h3>
<p><a name="scoped_default_constructor"><code>scoped_connection();</code></a>
<ul>
<li><b>Effects</b>: Sets the currently represented connection to the NULL connection.</li>
<li><b>Postconditions</b>: <code>!<b>this</b>-&gt;connected()</code>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="scoped_copy_constructor"><code>scoped_connection(<b>const</b> scoped_connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>this</code> references the connection referenced by <code>other</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="scoped_copy_connection_constructor"><code>scoped_connection(<b>const</b> connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>this</code> references the connection referenced by <code>other</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr><h3>Destructor</h3>
<p><a name="destructor">~<code>connection();</code></a>
<ul>
<li><b>Effects</b>: <code><b>this</b>-&gt;disconnect()</li>
</ul>
<hr><h3>Assignment and Swap</h3>
<p><a name="scoped_copy_assignment"><code>scoped_connection&amp; <b>operator=</b>(<b>const</b> scoped_connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>scoped_connection(other).swap(*<b>this</b>);</code>
<li><b>Returns</b>: <code>*<b>this</b></code></li>
</ul>
<p><a name="scoped_copy_connection_assignment"><code>scoped_connection&amp; <b>operator=</b>(<b>const</b> connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: <code>scoped_connection(other).swap(*<b>this</b>);</code>
<li><b>Returns</b>: <code>*<b>this</b></code></li>
</ul>
<p><a name="scoped_swap_member"><code><b>void</b> swap(scoped_connection&amp; other);</code></a>
<ul>
<li><b>Effects</b>: swaps the connections referenced in <code><b>this</b></code> and <code>other</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr><h2>Free Functions</h2>
<p><a name="swap_free"><code><b>void</b> swap(connection&amp c1, connection&amp; c2);</code></a>
<ul>
<li><b>Effects</b>: <code>c1.swap(c2)</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="scoped_swap_free"><code><b>void</b> swap(scoped_connection&amp c1, scoped_connection&amp; c2);</code></a>
<ul>
<li><b>Effects</b>: <code>c1.swap(c2)</code>.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Wed Mar 6 19:04:00 EST 2002
<!-- hhmts end -->
</body>
</html>

View File

@@ -0,0 +1,62 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: class templates signalN</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: class template <code>last_value</code></h1>
<h2>Header</h2>
<pre>
#include &lt;<a href="../../../../boost/signals/last_value.hpp">boost/signals/last_value.hpp</a>&gt;
</pre>
<h2>Synopsis</h2>
<pre>
<b>namespace</b> boost {
<b>template</b>&lt;<b>typename</b> T&gt;
<b>class</b> last_value {
<b>public</b>:
<b>typedef</b> T result_type;
<b>template</b>&lt;<b>typename</b> InputIterator&gt;
<a href="#call">result_type <b>operator</b>()(InputIterator, InputIterator) <b>const</b></a>;
};
<b>template</b>&lt;&gt;
<b>class</b> last_value&lt;void&gt; {
<b>public</b>:
<b>typedef</b> <em>implementation-defined</em> result_type; <em>// cannot be void</em>
<b>template</b>&lt;<b>typename</b> InputIterator&gt;
<a href="#void_call">result_type <b>operator</b>()(InputIterator, InputIterator) <b>const</b></a>;
};
}
</pre>
<hr><h2>Members</h2>
<p><a name="call"><code><b>template</b>&lt;<b>typename</b> InputIterator&gt;
result_type <b>operator</b>()(InputIterator first, InputIterator last) <b>const</b>;</code></a>
<ul>
<li><b>Precondition</b>: <code>first != last</code>.</li>
<li><b>Effects</b>: dereferences every iterator in the sequence <code>[first, last)</code>.</li>
<li><b>Returns</b>: the result of dereferencing the last iterator dereferenced.</li>
</ul>
<p><a name="void_call"><code><b>template</b>&lt;<b>typename</b> InputIterator&gt;
result_type <b>operator</b>()(InputIterator first, InputIterator last) <b>const</b>;</code></a>
<ul>
<li><b>Effects</b>: dereferences every iterator in the sequence <code>[first, last)</code>.</li>
<li><b>Returns</b>: a value that cannot be meaningfully used by the user, but not <code>void</code>.</li>
<li><b>Rationale</b>: a function that returns <code>void</code> often requires many workarounds within systems that compose function objects, and therefore we avoid returning <code>void</code> and instead opt to return an implementation-defined, useless value that still leaves the function object easily adaptable.</li>
</ul>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 14 21:14:07 EST 2002
<!-- hhmts end -->
</body>
</html>

41
doc/reference/signal.html Normal file
View File

@@ -0,0 +1,41 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: header &lt;boost/signal.hpp&gt;</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: header <code>&lt;boost/signal.hpp&gt;</code></h1>
<h2>Header</h2>
<pre>
#include &lt;<a href="../../../../boost/signal.hpp">boost/signal.hpp</a>&gt;
</pre>
<h2>Synopsis</h2>
<p> The specification form for the <code>signal</code> class template uses two positive integers, <em>BOOST_SIGNALS_MAX_ARGS</em> and <em>N</em>. The former describes the maximum number of function parameters that may be passed onto the underlying slots, whereas the latter describes the number of function parameters for a given instantiation of <code>signal</code>. <em>BOOST_SIGNALS_MAX_ARGS</em> is present in the header as a preprocessor macro defining the maximum number of arguments supported by the implementation.
<pre>
<b>namespace</b> boost {
<b>template</b>&lt;<b>typename</b> R,
<b>typename</b> T1 = <em>implementation-defined</em>,
<b>typename</b> T2 = <em>implementation-defined</em>,
...
<b>typename</b> T<em>BOOST_SIGNALS_MAX_ARGS</em> = <em>implementation-defined</em> &gt;
<b>class</b> signal : <b>public</b> <a href="signalN.html">signal<em>N</em></a>&lt;R, T1, T2, ..., T<em>N</em>&gt;
{
<b>template</b>&lt;<b>typename</b> Combiner&gt;
<b>struct</b> combiner {
<b>typedef</b> signal<em>N</em>&lt;R, T1, T2, ..., T<em>N</em>, Combiner&gt; type;
};
};
}
</pre>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 14 21:14:32 EST 2002
<!-- hhmts end -->
</body>
</html>

221
doc/reference/signalN.html Normal file
View File

@@ -0,0 +1,221 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: class templates signalN</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: class templates <code>signal<em>N</em></code></h1>
<h2>Headers</h2>
<p> <em>N</em> is the number of signal parameters supported. So the header <code>&lt;boost/signals/signal0.hpp&gt;</code> contains <code>signal0</code>, header <code>&lt;boost/signals/signal1.hpp&gt;</code> contains <code>signal1</code>, etc. The maximum number of signal parameters supported is implementation-defined, but must be at least 10.
<pre>
#include &lt;boost/signals/signal<em>N</em>.hpp&gt;
</pre>
<h2>Synopsis</h2>
<p> This document covers several related classes <code>signal<em>0</em></code>,
<code>signal<em>1</em></code>, <code>signal<em>2</em></code>,
etc., where the number suffix describes the number of function
parameters the signal and its connected slots will take. Instead
of enumerating all classes, a single pattern
<code>signal<em>N</em></code> will be described, where
<em>N</em> represents the number of function parameters.
<pre>
<b>namespace</b> boost {
<b>template</b>&lt;<b>typename</b> R,
<b>typename</b> T1,
<b>typename</b> T2,
...
<b>typename</b> T<em>N</em>,
<b>typename</b> <a href="#combiner">Combiner</a> = <a href="last_value.html">last_value</a>&lt;R&gt;,
<b>typename</b> <a href="#slot_group">Group</a> = <b>int</b>,
<b>typename</b> <a href="#group_compare">GroupCompare</a> = std::less&lt;Group&gt;,
<b>typename</b> <a href="#slot_function_type">SlotFunction</a> = <a href="../../../function/doc/reference.html">boost::function<em>N</em></a>&lt;R, T1, T2, ..., T<em>N</em>&gt; &gt;
<b>class</b> signal<em>N</em> :
<a href="../../../utility/utility.htm#noncopyable">boost::noncopyable</a> <em>// exposition only: class meets <a href="../../../thread/doc/overview.html#NonCopyable">Noncopyable</a> requirement</em>,
<a href="trackable.html">boost::trackable</a>
{
<b>public</b>:
<b>typedef</b> <b>typename</b> Combiner::result_type result_type;
<b>typedef</b> Combiner combiner_type;
<b>typedef</b> Group group_type;
<b>typedef</b> GroupCompare group_compare_type;
<b>typedef</b> SlotFunction slot_function_type;
<b>typedef</b> <a href="slot.html">slot</a>&lt;slot_function_type&gt; slot_type;
<b>typedef</b> <em>implementation-defined</em> <a href="#slot_result_type">slot_result_type</a>; <em>// if SlotFunction has a <b>void</b> return type, may not be <b>void</b>; otherwise it is the SlotFunction return type</em>
<b>typedef</b> <em>implementation-defined</em> <a href="#slot_call_iterator">slot_call_iterator</a>; <em>// <a href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with <code>value_type R</code>.</em>
<b>typedef</b> T1 argument_type; <em>// If N == 1 then signal models <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a></em>
<b>typedef</b> T1 first_argument_type; <em>// If N==2 then signal models <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a></em>
<b>typedef</b> T2 second_argument_type; <em>// If N==2 then signal models <a href="http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html">AdaptableBinaryFunction</a></em>
<b>typedef</b> T1 arg1_type;
<b>typedef</b> T2 arg2_type;
.
.
.
<b>typedef</b> T<em>N</em> arg<em>N</em>_type;
<a href="#constructor"><b>explicit</b> signal<em>N</em>(<b>const</b> combiner_type&amp; = combiner_type(), <b>const</b> group_compare_type&amp; = group_compare_type())</a>;
<a href="#destructor">~signal()</a>;
<a href="#connect">signals::connection connect(<b>const</b> slot_type&amp;)</a>;
<a href="#group_connect">signals::connection connect(<b>const</b> group_type<b>&amp;</b>, <b>const</b> slot_type&amp; slot)</a>;
<a href="#group_disconnect"><b>void</b> disconnect(<B>const</b> group_type<b>&amp;</b>)</a>;
<a href="#disconnect_all"><b>void</b> disconnect_all_slots()</a>;
<a href="#empty"><b>bool</b> empty() <b>const</b></a>;
<a href="#function_call_operator">result_type <b>operator()</b>(T1 a1, T2 a2, ..., T<em>N</em> a<em>N</em>);</a>
<a href="#function_call_operator_const">result_type <b>operator()</b>(T1 a1, T2 a2, ..., T<em>N</em> a<em>N</em>) <b>const</b>;</a>
<b>private</b>:
combiner_type combiner; <em>// exposition only</em>
};
}
</pre>
<hr><h2>Associated Types</h2>
<h3><a name="combiner">Combiner</a></h3>
<p>A Combiner is a function object that accepts an iterator sequence <code>[first, last)</code> and dereferences some number of the iterators within the sequence, then returns a value. The type of the iterators passed to the combiner will be the <a href="#slot_call_iterator">slot call iterator</a> type.
<h3><a name="slot_group">Group</a></h3>
<p> The slot group defines the type to be used to group connections. It must be <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>DefaultConstructible</code></a> and <a href="http://www.sgi.com/tech/stl/CopyConstructible.html"><code>CopyConstructible</code></a>.
<h3><a name="group_compare">Group comparison</a></h3>
<p> The group comparison is a <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><code>BinaryPredicate</code></a> where the argument types coincide with the <a href="#slot_group">group type</a>. It defines an ordering relation on the connection groups.
<h3><a name="slot_function_type">Slot Function</a></h3>
<p>The slot function type must be a function object adaptor capable of being constructed with another compatible function object (where "compatible" is defined by the slot function type itself). The slot function type must accept parameters of types <code>T1, T2, ..., T<em>N</em></code> and must return a result that is convertible to the template type parameter <code>R</code> of the signal; note that when <code>R</code> is void, any slot function return type will be ignored.
<p> For connections to other signals and to function object
references, the slot function type must be able to accept <a
href="../../../bind/ref.html"><code>reference_wrapper</code></a>
objects.
<hr><h2>Members</h2>
<h3><a name="slot_result_type">Slot Result Type</a></h3>
<p>type <code>slot_result_type</code>: when the <code>SlotFunction</code> returns <code><b>void</b></code>, the slot result type may be an implementation-defined type; otherwise, the slot result type must be the type retuned by <code>SlotFunction</code> function objects.
<h3><a name="slot_call_iterator">Slot Call Iterator</a></h3>
<p>type <code>slot_call_iterator</code>: an <a href="http://www.sgi.com/tech/stl/InputIterator.html"><code>InputIterator</code></a> whose <code>value_type</code> is <code>R</code>. The dereference operator of the <code>slot_call_iterator</code> is responsible for invoking the underlying slot given a specific set of arguments, and returning its result. The result must be cached to ensure that multiple dereferences of an iterator do not invoke the slot multiple times.
<hr><h3>Constructor</h3>
<p><code><b>explicit</b> <a name="constructor">signal<em>N</em>(<b>const</b> combiner_type&amp; = combiner_type(), <b>const</b> group_compare_type&amp; = group_compare_type());</a></code>
<ul>
<li><b>Effects</b>: initializes the signal to contain no slots, copies the given combiner into internal storage, and stores the given group comparison function object to compare groups.</li>
<li><b>Postconditions</b>: <code>this-&gt;empty();</code></li>
</ul>
<hr><h3>Destructor</h3>
<p><code><a name="destructor">~signal()</a>;</code>
<ul>
<li><b>Effects</b>: disconnects all slot connections.</li>
</ul>
<hr><h3>Connection Management</h3>
<p><code><a href="connection.html">signals::connection</a> <a name="connect">connect(<b>const</b> slot_type&amp; slot)</a>;</code>
<ul>
<li><b>Effects</b>: connects the signal <code>this</code> to the
incoming <code>slot</code>. If the slot is <em>inactive</em>,
i.e., any of the
<a href="trackable.html"><code>trackable</code></a> objects
bound by the slot call have been destroyed, then the call to
<code>connect</code> is a no-op.</li>
<li><b>Returns</b>: returns a
<a href="connection.html"><code>signals::connection</code></a>
object that
references the newly-created connection between the signal and
the slot; if the <code>slot</code> is inactive, returns a
disconnected connection.</li>
<li><b>Throws</b>: strong exception guarantee, where any exception thrown will cause the slot to not be connected to the signal.</li>
<li><b>Complexity</b>: <em>O(lg n)</em> where <em>n</em> is the
number of slots known to the signal.</li>
<li><b>Notes</b>: it is unspecified whether connecting a slot while
the signal is calling will result in the slot being called
immediately.</li>
</ul>
<p><code><a href="connection.html">signals::connection</a> <a name="group_connect">connect(<b>const</b> group_type<b>&amp;</b> group, <b>const</b> slot_type&amp; slot);</a></code>
<ul>
<li><b>Effects</b>: connects the given slot to the signal (i.e., <code>connect(slot)</code>), and associates this slot connection with the given group <code>group</code>.
<li><b>Returns</b>: returns a <a
href="connection.html"><code>signals::connection</code></a> object
that references the newly-created connection between the signal and
the slot.</li>
<li><b>Throws</b>: strong exception guarantee, where any exception
thrown will cause the slot to not be connected to the signal.</li>
<li><b>Complexity</b>: <em>O(lg n)</em> where <em>n</em> is the
number of slots known to the signal.</li>
<li><b>Notes</b>: it is unspecified whether connecting a slot while
the signal is calling will result in the slot being called
immediately.</li>
</ul>
<p><code><a name="group_disconnect"><b>void</b> disconnect(<b>const</b> group_type<b>&amp;</b> group);</a></code>
<ul>
<li><b>Effects</b>: any slots in the given group are disconnected.</li>
<li><b>Throws</b>: will not throw unless a user destructor
throws. If a user destructor throws, not all slots in this group may
be disconnected. </li>
<li><b>Complexity</b>: <em>O(lg n) + k</em> where <em>n is the
number of slots known to the signal and <em>k</em> is the number of
.</li>
</ul>
<p><code><a name="disconnect_all"><b>void</b> disconnect_all_slots()</a>;</code>
<ul>
<li><b>Effects</b>: disconnects all slots connected to the signal.</li>
<li><b>Postconditions</b>: <code>this-&gt;empty()</code>.</li>
<li><b>Throws</b>: if disconnecting a slot causes an exception to be
thrown, not all slots may be disconnected.</li>
<li><b>Complexity</b>: linear in the number of slots known to the signal.</li>
<li><b>Notes</b>: may be called at any time within the lifetime of
the signal, including during calls to the signal's slots.</li>
</ul>
<p><code><a name="empty"><b>bool</b> empty() <b>const</b></a>;</code>
<ul>
<li><b>Returns</b>: returns <code><b>true</b></code> if no slots are connected to the signal, and <code><b>false</b></code> otherwise.</li>
<li><b>Throws</b>: will not throw.</li>
<li><b>Complexity</b>: linear in the number of slots known to the signal.</li>
<li><b>Rationale</b>: slots can disconnect at any point in time, including while those same slots are being invoked. It is therefore possible that the implementation must search through a list of disconnected slots to determine if any slots are still connected.</li>
</ul>
<hr><h3>Signal Invocation</h3>
<p>
<pre>
<a name="function_call_operator">result_type <b>operator()</b>(T1 a1, T2 a2, ..., T<em>N</em> a<em>N</em>);</a>
<a name="function_call_operator_const">result_type <b>operator()</b>(T1 a1, T2 a2, ..., T<em>N</em> a<em>N</em>) <b>const</b>;</a>
</pre>
<ul>
<li><b>Effects</b>: invokes the combiner with a
<code>slot_call_iterator</code> range <code>[first, last)</code>
(i.e., <code>combiner(first, last)</code>) that iterates over the
results of calling each slot with the given set of parameters
<code>a1, a2, ..., a<em>N</em></code>. Slots are called according to
the partial ordering given by the group comparison function object,
with ungrouped slots called last. </li>
<li><b>Returns</b>: the result returned by the combiner.</li>
<li><b>Throws</b>: if an exception is thrown by a slot call, or if the combiner does not dereference any slot past some given slot, all slots after that slot in the internal list of connected slots will not be invoked.</li>
<li><b>Notes</b>: the <code><b>const</b></code> version of the
function call operator will invoke the combiner as
<code><b>const</b></code>, whereas the non-<code><b>const</b></code>
version will invoke the combiner as non-<code><b>const</b></code>.
<p>Ordering between members of a given group or between ungrouped
slots is unspecified.
<p> Calling the function call operator may invoke undefined behavior if no
slots are connected to the signal, depending on the combiner used. The
default combiner is well-defined for zero slots when the return type is
<code><b>void</b></code> but is undefined when the return type is any
other type (because there is no way to synthesize a return value).</li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Fri May 17 10:18:50 EDT 2002
<!-- hhmts end -->
</body>
</html>

48
doc/reference/slot.html Normal file
View File

@@ -0,0 +1,48 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: class template slot</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: class template slot</h1>
<h2>Header</h2>
<pre>
#include &lt;<a href="../../../../boost/signals/slot.hpp">boost/signals/slot.hpp</a>&gt;
</pre>
<h2>Synopsis</h2>
<p> The <code>slot</code> class template allows slots to be created
and passed as arguments to non-template functions. It is <a
href="http://www.sgi.com/tech/stl/CopyConstructible.html"><code>CopyConstructible</code></a>, but not <a href="http://www.sgi.com/tech/stl/DefaultConstructible.html"><code>DefaultConstructible</code></a> or <a href="http://www.sgi.com/tech/stl/Assignable.html"><code>Assignable</code></a>.
<pre>
<b>namespace</b> boost {
<b>template</b>&lt;<b>typename</b> <a href="signalN.html#slot_function_type">SlotFunction</a>&gt;
<b>class</b> slot {
<b>public</b>:
<b>template</b>&lt;<b>typename</b> Slot&gt; <a href="#constructor">slot(<b>const</b> Slot<b>&amp;</b>)</a>;
<b>private</b>:
SlotFunction stored_slot_function; <em>// exposition only</em>
};
}
</pre>
<hr><h3>Constructor</h3>
<p><code><b>template</b>&lt;<b>typename</b> Slot&gt; <a name="constructor">slot(<b>const</b> Slot<b>&amp;</b> slot)</a>;</code>
<ul>
<li><b>Effects</b>: initializes <code>this</code> to contain the
incoming <code>slot</code>, which may be any function object
that <a
href="signalN.html#slot_function_type"><code>SlotFunction</code></a> can be constructed with.
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu"></a></address>
<!-- Created: Fri Dec 28 10:58:18 EST 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 14 21:18:12 EST 2002
<!-- hhmts end -->
</body>
</html>

View File

@@ -0,0 +1,72 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals: Class trackable</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals: Class <code>trackable</code></h1>
<h2>Header</h2>
<pre>
#include &lt;<a href="../../../../boost/signals/trackable.hpp">boost/signals/trackable.hpp</a>&gt;
</pre>
<h2>Synopsis</h2>
<p>The <code>trackable</code> class is responsible for managing the automatic disconnection of signals and slots when an object that is bound as part of a slot is destroyed. The <code>trackable</code> class may only be used as a base class for some other class; when used as such, that class may be bound to function objects used as part of slots. The manner in which a the <code>trackable</code> object tracks the set of signal-slot connections it is a part of is implementation-defined.
<pre>
<b>namespace</b> boost {
<b>namespace</b> signals {
<b>class</b> trackable {
<b>protected</b>:
<a href="#default_constructor">trackable()</a>;
<a href="#copy_constructor">trackable(<b>const</b> trackable&amp;)</a>;
<a href="#destructor">~trackable()</a>;
<a href="#copy_assignment">trackable&amp; <b>operator=</b>(<b>const</b> trackable&amp;)</a>;
};
}
}
</pre>
<h2>Members</h2>
<hr><h3>Constructors</h3>
<p><a name="default_constructor"><code>trackable();</code></a>
<ul>
<li><b>Effects</b>: sets the list of connected slots to empty.</li>
<li><b>Throws</b>: will not throw.</li>
</ul>
<p><a name="copy_constructor"><code>trackable(<b>const</b> trackable&amp;);</code></a>
<ul>
<li><b>Effects</b>: sets the list of connected slots to empty.</li>
<li><b>Throws</b>: will not throw.</li>
<li><b>Rational</b>: signal-slot connections can only be created via calls to an explicit connect method, and therefore cannot be created here when trackable objects are copied.</li>
</ul>
<hr><h3>Destructor</h3>
<p><a name="destructor">~<code>trackable();</code></a>
<ul>
<li><b>Effects</b>: disconnects all connected slots.</li>
</ul>
<hr><h3>Assignment</h3>
<p><a name="copy_assignment"><code>trackable&amp; <b>operator=</b>(<b>const</b> trackable&amp; other);</code></a>
<ul>
<li><b>Effects</b>: disconnects all connected slots.</li>
<li><b>Returns</b>: <code>*<b>this</b></code></li>
<li><b>Rational</b>: signal-slot connections can only be created via calls to an explicit connect method, and therefore cannot be created here when trackable objects are copied.</li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu">Douglas Gregor</a></address>
<!-- Created: Fri Jul 13 10:57:20 EDT 2001 -->
<!-- hhmts start -->
Last modified: Wed Mar 6 19:03:23 EST 2002
<!-- hhmts end -->
</body>
</html>

View File

@@ -0,0 +1,62 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>function template visit_each</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">function template visit_each</h1>
<h2>Header</h2>
<pre>
#include &lt;<a href="../../../../boost/visit_each.hpp">boost/visit_each.hpp</a>&gt;
</pre>
<h2>Synopsis</h2>
<p>The <code>visit_each</code> mechanism allows a visitor to be
applied to every subobject in a given object. It is used by the
Signals library to discover trackable objects within a function
object, but other uses may surface if it used universally (e.g.,
conservative garbage collection). To fit within the
<code>visit_each</code> framework, a <code>visit_each</code>
overload must be supplied for each object type.
<pre>
<b>namespace</b> boost {
<b>template</b>&lt;<b>typename</b> Visitor, <b>typename</b> T&gt;
void <a href="#visit_each">visit_each(Visitor<b>&amp;</b>, <b>const</b> T<b>&amp;</b>, int)</a>;
}
</pre>
<hr><h2>Functions</h2>
<p><code><a name="visit_each"><b>template</b>&lt;<b>typename</b> Visitor, <b>typename</b> T&gt;
void visit_each(Visitor<b>&amp;</b> v, <b>const</b> T<b>&amp;</b> t, int)</a>;</code>
<ul>
<li><b>Effects</b>: <code>v(t)</code>, and for every subobject
<code>x</code> of <code>t</code>,
<ul>
<li>If <code>x</code> is a reference, executes
<code>v(<a href="../../../bind/ref.html">boost::ref</a>(x))</code>.</li>
<li>If <code>x</code> is not a reference, executes
<code>v(x)</code>.</li>
</ul>
<li><b>Returns</b>: nothing.</li>
<li><b>Notes</b>: the third parameter is <code>long</code> for the
fallback version of <code>visit_each</code> defined in
<code>&lt;<a
href="../../../../boost/visit_each.hpp">boost/visit_each.hpp</a>&gt;</code>, and the argument supplied to this third paramter must always be 0. The third parameter is an artifact of the widespread lack of proper function template ordering, and will be removed in the future.
<p>Library authors will be expected to add additional overloads
that specialize the <code>T</code> argument for their classes,
so that subobjects can be visited.</li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu"></a></address>
<!-- Created: Fri Dec 28 13:24:08 EST 2001 -->
<!-- hhmts start -->
Last modified: Thu Feb 14 21:19:03 EST 2002
<!-- hhmts end -->
</body>
</html>

22
doc/tutorial.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Boost.Signals Tutorial</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#800080">
<h1><IMG SRC="../../../c++boost.gif" WIDTH="276" HEIGHT="86" ALT="Boost">Boost.Signals Tutorial</h1>
<h2>Outline</h2>
<ul>
<li>
</ul>
<hr>
<address><a href="mailto:gregod@cs.rpi.edu"></a></address>
<!-- Created: Sat Apr 13 14:00:48 EDT 2002 -->
<!-- hhmts start -->
Last modified: Sat Apr 13 14:13:52 EDT 2002
<!-- hhmts end -->
</body>
</html>

45
example/Jamfile Normal file
View File

@@ -0,0 +1,45 @@
subproject libs/signals/example ;
exe button_click : <lib>../build/boost_signals
button_click.cpp
: <include>$(BOOST_ROOT)
;
exe difference_connection : <lib>../build/boost_signals
difference_connection.cpp
: <include>$(BOOST_ROOT)
;
exe disconnect_all : <lib>../build/boost_signals
disconnect_all.cpp
: <include>$(BOOST_ROOT)
;
exe first_positive : <lib>../build/boost_signals
first_positive.cpp
: <include>$(BOOST_ROOT)
;
exe maximum : <lib>../build/boost_signals
maximum.cpp
: <include>$(BOOST_ROOT)
;
exe print_sum_product : <lib>../build/boost_signals
print_sum_product.cpp
: <include>$(BOOST_ROOT)
;
exe quotient_controlling : <lib>../build/boost_signals
quotient_controlling.cpp
: <include>$(BOOST_ROOT)
;
exe quotient_named : <lib>../build/boost_signals
quotient_named.cpp
: <include>$(BOOST_ROOT)
;
exe no_function : <lib>../build/boost_signals
no_function.cpp
: <include>$(BOOST_ROOT)
;

65
example/button_click.cpp Normal file
View File

@@ -0,0 +1,65 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/bind.hpp>
#include <boost/signals/signal1.hpp>
#include <iostream>
struct print_string : public boost::signals::trackable {
typedef void result_type;
void print(const std::string& s) const { std::cout << s << std::endl; }
};
struct my_button {
typedef boost::signal1<void, const std::string&> click_signal_type;
typedef click_signal_type::slot_type click_slot_type;
boost::signals::connection on_click_connect(const click_slot_type& s)
{ return on_click.connect(s); }
my_button(const std::string& l) : label(l) {}
virtual ~my_button() {}
void click();
protected:
virtual void clicked() { on_click(label); }
private:
std::string label;
click_signal_type on_click;
};
void my_button::click()
{
clicked();
}
int main()
{
my_button* b = new my_button("OK!");
print_string* ps = new print_string();
b->on_click_connect(boost::bind(&print_string::print, ps, _1));
b->click(); // prints OK!
delete ps;
b->click(); // prints nothing
return 0;
}

View File

@@ -0,0 +1,54 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
#include <cassert>
struct print_sum {
void operator()(int x, int y) const { std::cout << x+y << std::endl; }
};
struct print_product {
void operator()(int x, int y) const { std::cout << x*y << std::endl; }
};
struct print_difference {
void operator()(int x, int y) const { std::cout << x-y << std::endl; }
};
int main()
{
boost::signal2<void, int, int> sig;
sig.connect(print_sum());
sig.connect(print_product());
sig(3, 5);
boost::signals::connection print_diff_con = sig.connect(print_difference());
// sig is still connected to print_diff_con
assert(print_diff_con.connected());
sig(5, 3); // prints 8, 15, and 2
print_diff_con.disconnect(); // disconnect the print_difference slot
sig(5, 3); // now prints 8 and 15, but not the difference
assert(!print_diff_con.connected()); // not connected any more
return 0;
}

View File

@@ -0,0 +1,77 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
#include <cassert>
struct print_sum {
void operator()(int x, int y) const { std::cout << x+y << std::endl; }
};
struct print_product {
void operator()(int x, int y) const { std::cout << x*y << std::endl; }
};
struct print_difference {
void operator()(int x, int y) const { std::cout << x-y << std::endl; }
};
struct print_quotient {
void operator()(int x, int y) const { std::cout << x/-y << std::endl; }
};
int main()
{
boost::signal2<void, int, int, boost::last_value<void>, std::string> sig;
sig.connect(print_sum());
sig.connect(print_product());
sig(3, 5);
boost::signals::connection print_diff_con = sig.connect(print_difference());
// sig is still connected to print_diff_con
assert(print_diff_con.connected());
sig(5, 3); // prints 8, 15, and 2
print_diff_con.disconnect(); // disconnect the print_difference slot
sig(5, 3); // now prints 8 and 15, but not the difference
assert(!print_diff_con.connected()); // not connected any more
{
boost::signals::scoped_connection c = sig.connect(print_quotient());
sig(5, 3); // prints 8, 15, and 1
} // c falls out of scope, so sig and print_quotient are disconnected
sig(5, 3); // prints 8 and 15
sig.connect("quotient", print_quotient());
sig(5, 3); // prints 8, 15, and 1
sig.disconnect("quotient");
sig(5, 3); // prints 8 and 15
std::cout << "Disconnected all slots" << std::endl;
sig.disconnect_all_slots();
assert(sig.empty());
sig(5, 3); // prints nothing - no slots are connected
return 0;
}

View File

@@ -0,0 +1,54 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signals/signal2.hpp>
#include <iostream>
template<typename T>
struct first_positive {
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
while (first != last && !(*first > 0)) { ++first; }
return (first == last) ? 0
: *first;
}
};
template<typename T>
struct noisy_divide {
typedef T result_type;
T operator()(const T& x, const T& y) const
{
std::cout << "Dividing " << x << " and " << y << std::endl;
return x/y;
}
};
int main()
{
boost::signal2<int, int, int, first_positive<int> > sig_positive;
sig_positive.connect(std::plus<int>());
sig_positive.connect(std::multiplies<int>());
sig_positive.connect(std::minus<int>());
sig_positive.connect(noisy_divide<int>());
assert(sig_positive(3, -5) == 8); // returns 8, but prints nothing
return 0;
}

44
example/maximum.cpp Normal file
View File

@@ -0,0 +1,44 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <algorithm>
#include <iostream>
#include <boost/signals/signal2.hpp>
template<typename T>
struct maximum {
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
if (first == last)
throw std::runtime_error("Cannot compute maximum of zero elements!");
return *std::max_element(first, last);
}
};
int main()
{
boost::signal2<int, int, int, maximum<int> > sig_max;
sig_max.connect(std::plus<int>());
sig_max.connect(std::multiplies<int>());
sig_max.connect(std::minus<int>());
sig_max.connect(std::divides<int>());
std::cout << sig_max(5, 3) << std::endl; // prints 15
return 0;
}

50
example/no_function.cpp Normal file
View File

@@ -0,0 +1,50 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
#include <string>
#include <functional>
void print_sum(int x, int y)
{
std::cout << "Sum = " << x+y << std::endl;
}
void print_product(int x, int y)
{
std::cout << "Product = " << x*y << std::endl;
}
void print_quotient(float x, float y)
{
std::cout << "Quotient = " << x/y << std::endl;
}
int main()
{
typedef boost::signal2<void, int, int, boost::last_value<void>,
std::string, std::less<std::string>,
void (*)(int, int)> sig_type;
sig_type sig;
sig.connect(&print_sum);
sig.connect(&print_product);
sig(3, 5); // print sum and product of 3 and 5
// should fail
// sig.connect(&print_quotient);
}

View File

@@ -0,0 +1,38 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
struct print_sum {
void operator()(int x, int y) const { std::cout << x+y << std::endl; }
};
struct print_product {
void operator()(int x, int y) const { std::cout << x*y << std::endl; }
};
int main()
{
boost::signal2<void, int, int> sig;
sig.connect(print_sum());
sig.connect(print_product());
sig(3, 5); // prints 8 and 15
return 0;
}

View File

@@ -0,0 +1,67 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
#include <cassert>
struct print_sum {
void operator()(int x, int y) const { std::cout << x+y << std::endl; }
};
struct print_product {
void operator()(int x, int y) const { std::cout << x*y << std::endl; }
};
struct print_difference {
void operator()(int x, int y) const { std::cout << x-y << std::endl; }
};
struct print_quotient {
void operator()(int x, int y) const { std::cout << x/-y << std::endl; }
};
int main()
{
boost::signal2<void, int, int> sig;
sig.connect(print_sum());
sig.connect(print_product());
sig(3, 5);
boost::signals::connection print_diff_con = sig.connect(print_difference());
// sig is still connected to print_diff_con
assert(print_diff_con.connected());
sig(5, 3); // prints 8, 15, and 2
print_diff_con.disconnect(); // disconnect the print_difference slot
sig(5, 3); // now prints 8 and 15, but not the difference
assert(!print_diff_con.connected()); // not connected any more
{
boost::signals::scoped_connection c = sig.connect(print_quotient());
sig(5, 3); // prints 8, 15, and 1
} // c falls out of scope, so sig and print_quotient are disconnected
sig(5, 3); // prints 8 and 15
return 0;
}

View File

@@ -0,0 +1,72 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <iostream>
#include <boost/signals/signal2.hpp>
#include <cassert>
struct print_sum {
void operator()(int x, int y) const { std::cout << x+y << std::endl; }
};
struct print_product {
void operator()(int x, int y) const { std::cout << x*y << std::endl; }
};
struct print_difference {
void operator()(int x, int y) const { std::cout << x-y << std::endl; }
};
struct print_quotient {
void operator()(int x, int y) const { std::cout << x/-y << std::endl; }
};
int main()
{
boost::signal2<void, int, int, boost::last_value<void>, std::string> sig;
sig.connect(print_sum());
sig.connect(print_product());
sig(3, 5);
boost::signals::connection print_diff_con = sig.connect(print_difference());
// sig is still connected to print_diff_con
assert(print_diff_con.connected());
sig(5, 3); // prints 8, 15, and 2
print_diff_con.disconnect(); // disconnect the print_difference slot
sig(5, 3); // now prints 8 and 15, but not the difference
assert(!print_diff_con.connected()); // not connected any more
{
boost::signals::scoped_connection c = sig.connect(print_quotient());
sig(5, 3); // prints 8, 15, and 1
} // c falls out of scope, so sig and print_quotient are disconnected
sig(5, 3); // prints 8 and 15
sig.connect("quotient", print_quotient());
sig(5, 3); // prints 8, 15, and 1
sig.disconnect("quotient");
sig(5, 3); // prints 8 and 15
return 0;
}

View File

@@ -0,0 +1,54 @@
// last_value function object (documented as part of Boost.Signals)
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_LAST_VALUE_HPP
#define BOOST_LAST_VALUE_HPP
#include <cassert>
namespace boost {
template<typename T>
struct last_value {
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
assert(first != last);
T value = *first++;
while (first != last)
value = *first++;
return value;
}
};
template<>
class last_value<void> {
struct unusable {};
public:
typedef unusable result_type;
template<typename InputIterator>
result_type
operator()(InputIterator first, InputIterator last) const
{
while (first != last)
*first++;
return result_type();
}
};
}
#endif // BOOST_SIGNALS_LAST_VALUE_HPP

388
include/boost/signal.hpp Normal file
View File

@@ -0,0 +1,388 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNAL_HPP
#define BOOST_SIGNAL_HPP
#define BOOST_SIGNALS_MAX_ARGS 10
#include <boost/config.hpp>
#include <boost/signals/signal0.hpp>
#include <boost/signals/signal1.hpp>
#include <boost/signals/signal2.hpp>
#include <boost/signals/signal3.hpp>
#include <boost/signals/signal4.hpp>
#include <boost/signals/signal5.hpp>
#include <boost/signals/signal6.hpp>
#include <boost/signals/signal7.hpp>
#include <boost/signals/signal8.hpp>
#include <boost/signals/signal9.hpp>
#include <boost/signals/signal10.hpp>
namespace boost {
namespace signals {
namespace detail {
// The unusable class is a placeholder for unused function arguments.
struct unused {};
// value=1 if the given type is not "unused"
template<typename T>
struct count_if_used
{
BOOST_STATIC_CONSTANT(int, value = 1);
};
// value=0 for unused types
template<>
struct count_if_used<unused>
{
BOOST_STATIC_CONSTANT(int, value = 0);
};
// Count the number of arguments (from the given set) which are not
// "unused" (therefore, count those arguments that are used).
template<typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8,
typename T9, typename T10>
struct count_used_args
{
BOOST_STATIC_CONSTANT(int, value =
(count_if_used<T1>::value +
count_if_used<T2>::value +
count_if_used<T3>::value +
count_if_used<T4>::value +
count_if_used<T5>::value +
count_if_used<T6>::value +
count_if_used<T7>::value +
count_if_used<T8>::value +
count_if_used<T9>::value +
count_if_used<T10>::value));
};
// Choose the appropriate underlying implementation
template<int Args> struct real_get_signal_impl {};
template<>
struct real_get_signal_impl<0>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal0<R, Combiner> type;
};
};
template<>
struct real_get_signal_impl<1>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal1<R, T1, Combiner> type;
};
};
template<>
struct real_get_signal_impl<2>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal2<R, T1, T2, Combiner> type;
};
};
template<>
struct real_get_signal_impl<3>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal3<R, T1, T2, T3, Combiner> type;
};
};
template<>
struct real_get_signal_impl<4>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal4<R, T1, T2, T3, T4, Combiner> type;
};
};
template<>
struct real_get_signal_impl<5>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal5<R, T1, T2, T3, T4, T5, Combiner>
type;
};
};
template<>
struct real_get_signal_impl<6>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal6<R, T1, T2, T3, T4, T5, T6, Combiner> type;
};
};
template<>
struct real_get_signal_impl<7>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal7<R, T1, T2, T3, T4, T5, T6, T7, Combiner> type;
};
};
template<>
struct real_get_signal_impl<8>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal8<R, T1, T2, T3, T4, T5, T6, T7, T8, Combiner> type;
};
};
template<>
struct real_get_signal_impl<9>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal9<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, Combiner> type;
};
};
template<>
struct real_get_signal_impl<10>
{
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct params
{
typedef signal10<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
Combiner> type;
};
};
template<
typename R,
typename T1,
typename T2,
typename T3,
typename T4,
typename T5,
typename T6,
typename T7,
typename T8,
typename T9,
typename T10,
typename Combiner = last_value<R>
>
struct get_signal_impl
{
typedef typename real_get_signal_impl<
(count_used_args<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>::value)
>::template params<R, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,
Combiner>::type
type;
};
} // end namespace detail
} // end namespace signals
// Very lightweight wrapper around the signalN classes that allows signals to
// be created where the number of arguments does not need to be part of the
// class name.
template<
typename R,
typename T1 = signals::detail::unused,
typename T2 = signals::detail::unused,
typename T3 = signals::detail::unused,
typename T4 = signals::detail::unused,
typename T5 = signals::detail::unused,
typename T6 = signals::detail::unused,
typename T7 = signals::detail::unused,
typename T8 = signals::detail::unused,
typename T9 = signals::detail::unused,
typename T10 = signals::detail::unused
>
class signal :
public signals::detail::get_signal_impl<R, T1, T2, T3, T4, T5, T6, T7,
T8, T9, T10>::type
{
public:
template<typename Combiner>
struct combiner {
typedef typename signals::detail::get_signal_impl<R, T1, T2, T3, T4, T5,
T6, T7, T8, T9, T10,
Combiner>::type
type;
};
};
} // end namespace boost
#endif // BOOST_SIGNAL_HPP

View File

@@ -0,0 +1,291 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_CONNECTION_HPP
#define BOOST_SIGNALS_CONNECTION_HPP
#include <boost/signals/detail/signals_common.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/operators.hpp>
#include <boost/any.hpp>
#include <list>
#include <cassert>
#include <utility>
namespace boost {
namespace signals {
class trackable;
namespace detail {
// Represents an object that has been bound as part of a slot, and how
// to notify that object of a disconnect
struct bound_object {
void* obj;
void* data;
void (*disconnect)(void*, void*);
bool operator==(const bound_object& other) const
{ return obj == other.obj && data == other.data; }
bool operator<(const bound_object& other) const
{ return obj < other.obj; }
};
// Describes the connection between a signal and the objects that are
// bound for a specific slot. Enables notification of the signal and the
// slots when a disconnect is requested.
struct basic_connection {
void* signal;
void* signal_data;
void (*signal_disconnect)(void*, void*);
std::list<bound_object> bound_objects;
};
} // end namespace detail
// The user may freely pass around the "connection" object and terminate
// the connection at any time using disconnect().
class connection :
private less_than_comparable1<connection>,
private equality_comparable1<connection>
{
public:
connection();
connection(const connection&);
~connection();
// Disconnect the signal and slot, if they are connected
void disconnect() const;
// Returns true if the signal and slot are connected
bool connected() const { return con.get() && con->signal_disconnect; }
// Comparison of connections
inline bool operator==(const connection& other) const;
inline bool operator<(const connection& other) const;
// Connection assignment
connection& operator=(const connection& other) ;
// Swap connections
void swap(connection& other);
public: // TBD: CHANGE THIS
// Set whether this connection object is controlling or not
void set_controlling() { controlling_connection = true; }
private:
friend class detail::signal_base_impl;
friend class detail::slot_base;
friend class trackable;
// Reset this connection to refer to a different actual connection
void reset(signals::detail::basic_connection*);
// Add a bound object to this connection (not for users)
void add_bound_object(const signals::detail::bound_object& b);
friend class signals::detail::bound_objects_visitor;
// Pointer to the actual contents of the connection
shared_ptr<signals::detail::basic_connection> con;
// True if the destruction of this connection object should disconnect
bool controlling_connection;
};
// Similar to connection, but will disconnect the connection when it is
// destroyed unless release() has been called.
class scoped_connection : public connection {
public:
scoped_connection() : connection(), released(false) {}
scoped_connection(const connection&);
scoped_connection(const scoped_connection&);
~scoped_connection();
connection release();
void swap(scoped_connection&);
scoped_connection& operator=(const connection&);
scoped_connection& operator=(const scoped_connection&);
private:
bool released;
};
inline connection::connection() :
con(), controlling_connection(false)
{
}
inline connection::connection(const connection& other) :
con(other.con), controlling_connection(other.controlling_connection)
{
}
inline connection::~connection()
{
if (controlling_connection) {
disconnect();
}
}
inline void
connection::reset(signals::detail::basic_connection* new_con)
{
con.reset(new_con);
}
inline void
connection::add_bound_object(const signals::detail::bound_object& b)
{
assert(con.get());
con->bound_objects.push_back(b);
}
inline bool connection::operator==(const connection& other) const
{
return con.get() == other.con.get();
}
inline bool connection::operator<(const connection& other) const
{
return con.get() < other.con.get();
}
inline connection& connection::operator=(const connection& other)
{
connection(other).swap(*this);
return *this;
}
inline void connection::swap(connection& other)
{
this->con.swap(other.con);
std::swap(this->controlling_connection, other.controlling_connection);
}
inline void swap(connection& c1, connection& c2)
{
c1.swap(c2);
}
inline scoped_connection::scoped_connection(const connection& other) :
connection(other),
released(false)
{
}
inline
scoped_connection::scoped_connection(const scoped_connection& other) :
connection(other),
released(other.released)
{
}
inline scoped_connection::~scoped_connection()
{
if (!released) {
this->disconnect();
}
}
inline connection scoped_connection::release()
{
released = true;
return *this;
}
inline void scoped_connection::swap(scoped_connection& other)
{
this->connection::swap(other);
bool other_released = other.released;
other.released = this->released;
this->released = other_released;
}
inline void swap(scoped_connection& c1, scoped_connection& c2)
{
c1.swap(c2);
}
inline scoped_connection&
scoped_connection::operator=(const connection& other)
{
scoped_connection(other).swap(*this);
return *this;
}
inline scoped_connection&
scoped_connection::operator=(const scoped_connection& other)
{
scoped_connection(other).swap(*this);
return *this;
}
namespace detail {
struct connection_slot_pair {
connection first;
any second;
connection_slot_pair() {}
connection_slot_pair(const connection& c, const any& a)
: first(c), second(a)
{
}
// Dummys to allow explicit instantiation to work
bool operator==(const connection_slot_pair&) const { return false; }
bool operator<(const connection_slot_pair&) const { return false;}
};
// Determines if the underlying connection is disconnected
struct is_disconnected {
typedef std::pair<const any, connection_slot_pair> argument_type;
typedef bool result_type;
inline bool operator()(const argument_type& c) const
{
return !c.second.first.connected();
}
};
// Autodisconnects the bound object when it is destroyed unless the
// release method is invoked.
class auto_disconnect_bound_object {
public:
auto_disconnect_bound_object(const bound_object& b) :
binding(b), auto_disconnect(true)
{
}
~auto_disconnect_bound_object()
{
if (auto_disconnect)
binding.disconnect(binding.obj, binding.data);
}
void release() { auto_disconnect = false; }
private:
bound_object binding;
bool auto_disconnect;
};
} // end namespace detail
} // end namespace signals
} // end namespace boost
#endif // BOOST_SIGNALS_CONNECTION_HPP

View File

@@ -0,0 +1,138 @@
#!/usr/bin/perl -w
#
# Boost.Signals library
#
# Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
#
# Permission to copy, use, sell and distribute this software is granted
# provided this copyright notice appears in all copies.
# Permission to modify the code and to distribute modified code is granted
# provided this copyright notice appears in all copies, and a notice
# that the code was modified is included with the copyright notice.
#
# This software is provided "as is" without express or implied warranty,
# and with no claim as to its suitability for any purpose.
#
# For more information, see http://www.boost.org
use English;
if ($#ARGV < 0) {
print "Usage: perl gen_signal_N <number of arguments>\n";
exit;
}
$totalNumArgs = $ARGV[0];
for ($numArgs = 0; $numArgs <= $totalNumArgs; ++$numArgs) {
open OUT, ">signal$numArgs.hpp";
print OUT "// Boost.Signals library\n";
print OUT "//\n";
print OUT "// Copyright (C) 2001 Doug Gregor (gregod\@cs.rpi.edu)\n";
print OUT "//\n";
print OUT "// Permission to copy, use, sell and distribute this software is granted\n";
print OUT "// provided this copyright notice appears in all copies.\n";
print OUT "// Permission to modify the code and to distribute modified code is granted\n";
print OUT "// provided this copyright notice appears in all copies, and a notice\n";
print OUT "// that the code was modified is included with the copyright notice.\n";
print OUT "//\n";
print OUT "// This software is provided \"as is\" without express or implied warranty,\n";
print OUT "// and with no claim as to its suitability for any purpose.\n";
print OUT " \n";
print OUT "// For more information, see http://www.boost.org\n";
print OUT "\n";
print OUT "#ifndef BOOST_SIGNALS_SIGNAL" . $numArgs . "_HEADER\n";
print OUT "#define BOOST_SIGNALS_SIGNAL" , $numArgs . "_HEADER\n";
print OUT "\n";
print OUT "#define BOOST_SIGNALS_NUM_ARGS $numArgs\n";
$templateParms = "";
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$templateParms .= ", ";
}
$templateParms .= "typename T$i";
}
print OUT "#define BOOST_SIGNALS_TEMPLATE_PARMS $templateParms\n";
$_ = $templateParms;
s/typename //g;
$templateArgs = $_;
print OUT "#define BOOST_SIGNALS_TEMPLATE_ARGS $templateArgs\n";
$parms = "";
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$parms .= ", ";
}
$parms .= "T$i a$i";
}
print OUT "#define BOOST_SIGNALS_PARMS $parms\n";
$args = "";
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$args .= ", ";
}
$args .= "a$i";
}
print OUT "#define BOOST_SIGNALS_ARGS $args\n";
$boundArgs = "";
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$boundArgs .= ", ";
}
$boundArgs .= "args->a$i";
}
print OUT "#define BOOST_SIGNALS_BOUND_ARGS $boundArgs\n";
$argsAsMembers = "";
for ($i = 1; $i <= $numArgs; ++$i) {
$argsAsMembers .= "T$i a$i;";
}
print OUT "#define BOOST_SIGNALS_ARGS_AS_MEMBERS $argsAsMembers\n";
$copyParms = "";
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$copyParms .= ", ";
}
$copyParms .= "T$i ia$i";
}
print OUT "#define BOOST_SIGNALS_COPY_PARMS $copyParms\n";
$initArgs = "";
if ($numArgs > 0) {
$initArgs = ":";
}
for ($i = 1; $i <= $numArgs; ++$i) {
if ($i > 1) {
$initArgs .= ", ";
}
$initArgs .= "a$i(ia$i)";
}
print OUT "#define BOOST_SIGNALS_INIT_ARGS $initArgs\n";
$argTypes = "";
for ($i = 1; $i <= $numArgs; ++$i) {
$argTypes .= "typedef T$i arg". ($i+1) . "_type; ";
}
print OUT "#define BOOST_SIGNALS_ARG_TYPES $argTypes\n";
print OUT "\n";
print OUT "#include <boost/signals/signal_template.hpp>\n";
print OUT "\n";
print OUT "#undef BOOST_SIGNALS_ARG_TYPES\n";
print OUT "#undef BOOST_SIGNALS_INIT_ARGS\n";
print OUT "#undef BOOST_SIGNALS_COPY_PARMS\n";
print OUT "#undef BOOST_SIGNALS_ARGS_AS_MEMBERS\n";
print OUT "#undef BOOST_SIGNALS_BOUND_ARGS\n";
print OUT "#undef BOOST_SIGNALS_ARGS\n";
print OUT "#undef BOOST_SIGNALS_PARMS\n";
print OUT "#undef BOOST_SIGNALS_TEMPLATE_ARGS\n";
print OUT "#undef BOOST_SIGNALS_TEMPLATE_PARMS\n";
print OUT "#undef BOOST_SIGNALS_NUM_ARGS\n";
print OUT "\n";
print OUT "#endif // BOOST_SIGNALS_SIGNAL" . $numArgs . "_HEADER\n";
close OUT;
}

View File

@@ -0,0 +1,188 @@
// Boost.Signals library
//
// Copyright (C) 2001-2 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL_BASE_HEADER
#define BOOST_SIGNALS_SIGNAL_BASE_HEADER
#include <boost/signals/detail/signals_common.hpp>
#include <boost/signals/connection.hpp>
#include <boost/signals/trackable.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/any.hpp>
#include <boost/utility.hpp>
#include <boost/function/function2.hpp>
#include <map>
#include <utility>
#include <vector>
namespace boost {
namespace signals {
namespace detail {
// Forward declaration for the mapping from slot names to connections
class named_slot_map;
// This function object bridges from a pair of any objects that hold
// values of type Key to the underlying function object that compares
// values of type Key.
template<typename Compare, typename Key>
class any_bridge_compare {
public:
typedef bool result_type;
typedef const any& first_argument_type;
typedef const any& second_argument_type;
any_bridge_compare(const Compare& c) : comp(c) {}
bool operator()(const any& k1, const any& k2) const
{
// if k1 is empty, then it precedes nothing
if (k1.empty())
return false;
// if k2 is empty, then k1 must precede it
if (k2.empty())
return true;
// Neither is empty, so compare their values to order them
// The strange */& is so that we will get a reference to the
// value stored in the any object instead of a copy
return comp(*any_cast<Key>(&k1), *any_cast<Key>(&k2));
}
private:
Compare comp;
};
// Must be constructed before calling the slots, because it safely
// manages call depth
class call_notification {
public:
call_notification(const shared_ptr<signal_base_impl>&);
~call_notification();
shared_ptr<signal_base_impl> impl;
};
// Implementation of base class for all signals. It handles the
// management of the underlying slot lists.
class signal_base_impl {
public:
friend class call_notification;
typedef function2<bool, any, any> compare_type;
// Make sure that an exception does not cause the "clearing" flag to
// remain set
class temporarily_set_clearing {
public:
temporarily_set_clearing(signal_base_impl* b) : base(b)
{
base->flags.clearing = true;
}
~temporarily_set_clearing()
{
base->flags.clearing = false;
}
private:
signal_base_impl* base;
};
friend class temporarily_set_clearing;
signal_base_impl(const compare_type&);
~signal_base_impl();
// Disconnect all slots connected to this signal
void disconnect_all_slots();
// Are there any connected slots?
bool empty() const;
// Disconnect all slots in the given group
void disconnect(const any&);
// We're being notified that a slot has disconnected
static void slot_disconnected(void* obj, void* data);
connection connect_slot(const any& slot,
const any& name,
const std::vector<const trackable*>&);
private:
// Remove all of the slots that have been marked "disconnected"
void remove_disconnected_slots() const;
public:
// Our call depth when invoking slots (> 1 when we have a loop)
mutable int call_depth;
struct {
// True if some slots have disconnected, but we were not able to
// remove them from the list of slots because there are valid
// iterators into the slot list
mutable bool delayed_disconnect:1;
// True if we are disconnecting all disconnected slots
bool clearing:1;
} flags;
// Slots
typedef std::multimap<any, connection_slot_pair, compare_type>
slot_container_type;
typedef slot_container_type::iterator slot_iterator;
typedef slot_container_type::value_type stored_slot_type;
mutable slot_container_type slots;
};
class signal_base : public noncopyable {
public:
typedef signal_base_impl::compare_type compare_type;
friend class call_notification;
signal_base(const compare_type& comp) : impl()
{
impl.reset(new signal_base_impl(comp));
}
~signal_base();
public:
// Disconnect all slots connected to this signal
void disconnect_all_slots() { impl->disconnect_all_slots(); }
// Are there any connected slots?
bool empty() const { return impl->empty(); }
protected:
connection connect_slot(const any& slot,
const any& name,
const std::vector<const trackable*>& bound)
{
return impl->connect_slot(slot, name, bound);
}
typedef signal_base_impl::slot_iterator slot_iterator;
typedef signal_base_impl::stored_slot_type stored_slot_type;
shared_ptr<signal_base_impl> impl;
};
} // end namespace detail
} // end namespace signals
} // end namespace boost
#endif // BOOST_SIGNALS_SIGNAL_BASE_HEADER

View File

@@ -0,0 +1,155 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_COMMON_HEADER
#define BOOST_SIGNALS_COMMON_HEADER
#include <boost/type_traits/conversion_traits.hpp>
#include <boost/ref.hpp>
namespace boost {
namespace signals {
namespace detail {
// The unusable class is a placeholder for unused function arguments
// It is also completely unusable except that it constructable from
// anything. This helps compilers without partial specialization
// handle slots returning void.
struct unusable {
unusable() {}
};
// Determine the result type of a slot call
template<typename R>
struct slot_result_type {
typedef R type;
};
template<>
struct slot_result_type<void> {
typedef unusable type;
};
// Determine if the given type T is a signal
class signal_base;
template<typename T>
struct is_signal {
BOOST_STATIC_CONSTANT(bool,
value = (is_convertible<T*, signal_base*>::value));
};
/*
* The IF implementation is temporary code. When a Boost metaprogramming
* library is introduced, Boost.Signals will use it instead.
*/
namespace intimate {
struct SelectThen
{
template<typename Then, typename Else>
struct Result
{
typedef Then type;
};
};
struct SelectElse
{
template<typename Then, typename Else>
struct Result
{
typedef Else type;
};
};
template<bool Condition>
struct Selector
{
typedef SelectThen type;
};
template<>
struct Selector<false>
{
typedef SelectElse type;
};
} // end namespace intimate
template<bool Condition, typename Then, typename Else>
struct IF
{
typedef typename intimate::Selector<Condition>::type select;
typedef typename select::template Result<Then,Else>::type type;
};
// Determine if the incoming argument is a reference_wrapper
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
struct is_ref
{
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
struct is_ref<reference_wrapper<T> >
{
BOOST_STATIC_CONSTANT(bool, value = true);
};
#else // no partial specialization
typedef char yes_type;
typedef double no_type;
no_type is_ref_tester(...);
template<typename T>
yes_type is_ref_tester(reference_wrapper<T>*);
template<typename T>
struct is_ref
{
static T* t;
BOOST_STATIC_CONSTANT(bool,
value = (sizeof(is_ref_tester(t)) == sizeof(yes_type)));
};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// A slot can be a signal, a reference to a function object, or a
// function object.
struct signal_tag {};
struct reference_tag {};
struct value_tag {};
// Classify the given slot as a signal, a reference-to-slot, or a
// standard slot
template<typename S>
class get_slot_tag {
typedef typename IF<(is_signal<S>::value),
signal_tag,
value_tag>::type signal_or_value;
public:
typedef typename IF<(is_ref<S>::value),
reference_tag,
signal_or_value>::type type;
};
// Forward declaration needed in lots of places
class signal_base_impl;
class bound_objects_visitor;
class slot_base;
} // end namespace detail
} // end namespace signals
} // end namespace boost
#endif // BOOST_SIGNALS_COMMON_HEADER

View File

@@ -0,0 +1,119 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SLOT_CALL_ITERATOR
#define BOOST_SIGNALS_SLOT_CALL_ITERATOR
#include <functional>
#include <boost/iterator_adaptors.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/signals/connection.hpp>
namespace boost {
namespace signals {
namespace detail {
// A cached return value from a slot
template<typename T>
struct cached_return_value {
cached_return_value(const T& t) : value(t) {}
T value;
};
// Generates a slot call iterator. Essentially, this is an iterator that:
// - skips over disconnected slots in the underlying list
// - calls the connected slots when dereferenced
// - caches the result of calling the slots
template<typename Function, typename Iterator>
class slot_call_policies : public default_iterator_policies {
public:
typedef typename Function::result_type result_type;
slot_call_policies() {}
slot_call_policies(const Iterator& x, Function fi) :
end(x), f(fi), cache()
{
}
void initialize(Iterator& x)
{
x = std::find_if(x, end, std::not1(is_disconnected()));
cache.reset();
}
template <class IteratorAdaptor>
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor& x) const
{
if (!cache.get()) {
cache.reset(new cached_return_value<result_type>(f(*x.base())));
}
return cache->value;
}
template<typename IteratorAdaptor>
void increment(IteratorAdaptor& x)
{
++x.base();
x.base() = std::find_if(x.base(), x.policies().end,
std::not1(is_disconnected()));
cache.reset();
}
template<typename IteratorAdaptor1, typename IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{
Iterator xb = std::find_if(x.base(), x.policies().end,
std::not1(is_disconnected()));
Iterator yb = std::find_if(y.base(), y.policies().end,
std::not1(is_disconnected()));
const_cast<IteratorAdaptor1&>(x).base() = xb;
const_cast<IteratorAdaptor1&>(y).base() = yb;
return xb == yb;
}
private:
Iterator end;
Function f;
mutable shared_ptr< cached_return_value<result_type> > cache;
};
template<typename Function, typename Iterator>
class slot_call_iterator_generator {
private:
typedef typename Function::result_type value_type;
public:
typedef slot_call_policies<Function, Iterator> policy_type;
typedef iterator_adaptor<Iterator, policy_type, value_type,
value_type&, value_type*,
std::input_iterator_tag> type;
};
template<typename Function, typename Iterator>
inline typename slot_call_iterator_generator<Function, Iterator>::type
make_slot_call_iterator(Iterator first, Iterator last, Function f)
{
typedef slot_call_iterator_generator<Function, Iterator> gen;
typedef typename gen::type sc_iterator;
typedef typename gen::policy_type sc_policy;
return sc_iterator(first, sc_policy(last, f));
}
} // end namespace detail
} // end namespace signals
} // end namespace boost
#endif // BOOST_SIGNALS_SLOT_CALL_ITERATOR

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL0_HEADER
#define BOOST_SIGNALS_SIGNAL0_HEADER
#define BOOST_SIGNALS_NUM_ARGS 0
#define BOOST_SIGNALS_TEMPLATE_PARMS
#define BOOST_SIGNALS_TEMPLATE_ARGS
#define BOOST_SIGNALS_PARMS
#define BOOST_SIGNALS_ARGS
#define BOOST_SIGNALS_BOUND_ARGS
#define BOOST_SIGNALS_ARGS_AS_MEMBERS
#define BOOST_SIGNALS_COPY_PARMS
#define BOOST_SIGNALS_INIT_ARGS
#define BOOST_SIGNALS_ARG_TYPES
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL0_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL1_HEADER
#define BOOST_SIGNALS_SIGNAL1_HEADER
#define BOOST_SIGNALS_NUM_ARGS 1
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1
#define BOOST_SIGNALS_TEMPLATE_ARGS T1
#define BOOST_SIGNALS_PARMS T1 a1
#define BOOST_SIGNALS_ARGS a1
#define BOOST_SIGNALS_BOUND_ARGS args->a1
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL1_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL10_HEADER
#define BOOST_SIGNALS_SIGNAL10_HEADER
#define BOOST_SIGNALS_NUM_ARGS 10
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5, T6, T7, T8, T9, T10
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9, T10 a10
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9, a10
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5, args->a6, args->a7, args->a8, args->a9, args->a10
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;T6 a6;T7 a7;T8 a8;T9 a9;T10 a10;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5, T6 ia6, T7 ia7, T8 ia8, T9 ia9, T10 ia10
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5), a6(ia6), a7(ia7), a8(ia8), a9(ia9), a10(ia10)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type; typedef T7 arg8_type; typedef T8 arg9_type; typedef T9 arg10_type; typedef T10 arg11_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL10_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL2_HEADER
#define BOOST_SIGNALS_SIGNAL2_HEADER
#define BOOST_SIGNALS_NUM_ARGS 2
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2
#define BOOST_SIGNALS_ARGS a1, a2
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL2_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL3_HEADER
#define BOOST_SIGNALS_SIGNAL3_HEADER
#define BOOST_SIGNALS_NUM_ARGS 3
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3
#define BOOST_SIGNALS_ARGS a1, a2, a3
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL3_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL4_HEADER
#define BOOST_SIGNALS_SIGNAL4_HEADER
#define BOOST_SIGNALS_NUM_ARGS 4
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL4_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL5_HEADER
#define BOOST_SIGNALS_SIGNAL5_HEADER
#define BOOST_SIGNALS_NUM_ARGS 5
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL5_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL6_HEADER
#define BOOST_SIGNALS_SIGNAL6_HEADER
#define BOOST_SIGNALS_NUM_ARGS 6
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5, typename T6
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5, T6
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5, a6
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5, args->a6
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;T6 a6;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5, T6 ia6
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5), a6(ia6)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL6_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL7_HEADER
#define BOOST_SIGNALS_SIGNAL7_HEADER
#define BOOST_SIGNALS_NUM_ARGS 7
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5, T6, T7
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5, a6, a7
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5, args->a6, args->a7
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;T6 a6;T7 a7;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5, T6 ia6, T7 ia7
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5), a6(ia6), a7(ia7)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type; typedef T7 arg8_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL7_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL8_HEADER
#define BOOST_SIGNALS_SIGNAL8_HEADER
#define BOOST_SIGNALS_NUM_ARGS 8
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5, T6, T7, T8
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5, a6, a7, a8
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5, args->a6, args->a7, args->a8
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;T6 a6;T7 a7;T8 a8;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5, T6 ia6, T7 ia7, T8 ia8
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5), a6(ia6), a7(ia7), a8(ia8)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type; typedef T7 arg8_type; typedef T8 arg9_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL8_HEADER

View File

@@ -0,0 +1,43 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SIGNAL9_HEADER
#define BOOST_SIGNALS_SIGNAL9_HEADER
#define BOOST_SIGNALS_NUM_ARGS 9
#define BOOST_SIGNALS_TEMPLATE_PARMS typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9
#define BOOST_SIGNALS_TEMPLATE_ARGS T1, T2, T3, T4, T5, T6, T7, T8, T9
#define BOOST_SIGNALS_PARMS T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8, T9 a9
#define BOOST_SIGNALS_ARGS a1, a2, a3, a4, a5, a6, a7, a8, a9
#define BOOST_SIGNALS_BOUND_ARGS args->a1, args->a2, args->a3, args->a4, args->a5, args->a6, args->a7, args->a8, args->a9
#define BOOST_SIGNALS_ARGS_AS_MEMBERS T1 a1;T2 a2;T3 a3;T4 a4;T5 a5;T6 a6;T7 a7;T8 a8;T9 a9;
#define BOOST_SIGNALS_COPY_PARMS T1 ia1, T2 ia2, T3 ia3, T4 ia4, T5 ia5, T6 ia6, T7 ia7, T8 ia8, T9 ia9
#define BOOST_SIGNALS_INIT_ARGS :a1(ia1), a2(ia2), a3(ia3), a4(ia4), a5(ia5), a6(ia6), a7(ia7), a8(ia8), a9(ia9)
#define BOOST_SIGNALS_ARG_TYPES typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type; typedef T7 arg8_type; typedef T8 arg9_type; typedef T9 arg10_type;
#include <boost/signals/signal_template.hpp>
#undef BOOST_SIGNALS_ARG_TYPES
#undef BOOST_SIGNALS_INIT_ARGS
#undef BOOST_SIGNALS_COPY_PARMS
#undef BOOST_SIGNALS_ARGS_AS_MEMBERS
#undef BOOST_SIGNALS_BOUND_ARGS
#undef BOOST_SIGNALS_ARGS
#undef BOOST_SIGNALS_PARMS
#undef BOOST_SIGNALS_TEMPLATE_ARGS
#undef BOOST_SIGNALS_TEMPLATE_PARMS
#undef BOOST_SIGNALS_NUM_ARGS
#endif // BOOST_SIGNALS_SIGNAL9_HEADER

View File

@@ -0,0 +1,353 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
// This file intentionally does not have include guards, because it is meant
// to be included multiple times (one for each signalN class). The
// BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED macro merely serves to
// suppress reinclusion of the files that this header depends on.
#ifndef BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
#define BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
# include <boost/config.hpp>
# include <boost/signals/connection.hpp>
# include <boost/utility.hpp>
# include <boost/ref.hpp>
# include <boost/signals/slot.hpp>
# include <boost/last_value.hpp>
# include <boost/signals/detail/signal_base.hpp>
# include <boost/signals/detail/slot_call_iterator.hpp>
# include <cassert>
# include <functional>
# include <memory>
# include <string>
#endif // !BOOST_SIGNALS_SIGNAL_TEMPLATE_HEADER_INCLUDED
// Include the appropriate functionN header
#define BOOST_SIGNAL_FUNCTION_N_HEADER BOOST_JOIN(<boost/function/function,BOOST_SIGNALS_NUM_ARGS.hpp>)
#include BOOST_SIGNAL_FUNCTION_N_HEADER
// Determine if a comma should follow a listing of the arguments/parameters
#if BOOST_SIGNALS_NUM_ARGS == 0
# define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
#else
# define BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS ,
#endif // BOOST_SIGNALS_NUM_ARGS > 0
// Define class names used
#define BOOST_SIGNALS_SIGNAL BOOST_JOIN(signal,BOOST_SIGNALS_NUM_ARGS)
#define BOOST_SIGNALS_FUNCTION BOOST_JOIN(function,BOOST_SIGNALS_NUM_ARGS)
#define BOOST_SIGNALS_ARGS_STRUCT BOOST_JOIN(args,BOOST_SIGNALS_NUM_ARGS)
#define BOOST_SIGNALS_CALL_BOUND BOOST_JOIN(call_bound,BOOST_SIGNALS_NUM_ARGS)
// Define commonly-used instantiations
#define BOOST_SIGNALS_ARGS_STRUCT_INST \
signals::detail::BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>
namespace boost {
namespace signals {
namespace detail {
// Holds the arguments for a bound slot call in a single place
template<BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Dummy = int>
struct BOOST_SIGNALS_ARGS_STRUCT {
BOOST_SIGNALS_ARGS_STRUCT(BOOST_SIGNALS_COPY_PARMS)
BOOST_SIGNALS_INIT_ARGS
{
}
BOOST_SIGNALS_ARGS_AS_MEMBERS
};
// Function object that calls the function object given to it, passing
// the bound arguments along to that underlying function object
template<typename R>
struct BOOST_SIGNALS_CALL_BOUND {
template<BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename F>
struct caller {
typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
args_type;
args_type args;
typedef R result_type;
caller() {}
caller(args_type a) : args(a) {}
template<typename Pair>
R operator()(const Pair& slot) const
{
F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
return (*target)(BOOST_SIGNALS_BOUND_ARGS);
}
};
};
template<>
struct BOOST_SIGNALS_CALL_BOUND<void> {
template<BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename F>
struct caller {
typedef BOOST_SIGNALS_ARGS_STRUCT<BOOST_SIGNALS_TEMPLATE_ARGS>*
args_type;
args_type args;
typedef unusable result_type;
caller(args_type a) : args(a) {}
template<typename Pair>
unusable operator()(const Pair& slot) const
{
F* target = const_cast<F*>(any_cast<F>(&slot.second.second));
(*target)(BOOST_SIGNALS_BOUND_ARGS);
return unusable();
}
};
};
} // namespace detail
} // namespace signals
// The actual signalN class
template<
typename R,
BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Combiner = last_value<R>,
typename Group = int,
typename GroupCompare = std::less<Group>,
typename SlotFunction = BOOST_SIGNALS_FUNCTION<
R BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
BOOST_SIGNALS_TEMPLATE_ARGS>
>
class BOOST_SIGNALS_SIGNAL :
public signals::detail::signal_base, // management of slot list
public signals::trackable // signals are trackable
{
public:
// The slot function type
typedef SlotFunction slot_function_type;
// Result type of a slot
typedef typename signals::detail::slot_result_type<R>::type
slot_result_type;
// Argument types
BOOST_SIGNALS_ARG_TYPES
#if BOOST_SIGNALS_NUM_ARGS == 1
typedef T1 argument_type;
#elif BOOST_SIGNALS_NUM_ARGS == 2
typedef T1 first_argument_type;
typedef T2 second_argument_type;
#endif
private:
// The real slot name comparison object type
typedef signals::detail::any_bridge_compare<GroupCompare, Group>
real_group_compare_type;
// The function object passed to the slot call iterator that will call
// the underlying slot function with its arguments bound
typedef signals::detail::BOOST_SIGNALS_CALL_BOUND<R>
outer_bound_slot_caller;
typedef typename outer_bound_slot_caller::template
caller<BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
slot_function_type>
call_bound_slot;
public:
// Combiner's result type
typedef typename Combiner::result_type result_type;
// Combiner type
typedef Combiner combiner_type;
// Slot type
typedef slot<slot_function_type> slot_type;
// Slot name type and comparison
typedef Group group_type;
typedef GroupCompare group_compare_type;
typedef typename signals::detail::slot_call_iterator_generator<
call_bound_slot,
slot_iterator>::type slot_call_iterator;
explicit
BOOST_SIGNALS_SIGNAL(const Combiner& c = Combiner(),
const GroupCompare& comp = GroupCompare()) :
signals::detail::signal_base(real_group_compare_type(comp)),
combiner(c)
{
}
// Connect a slot to this signal
signals::connection connect(const slot_type&);
signals::connection connect(const group_type&, const slot_type&);
// Disconnect a named slot
void disconnect(const group_type& group)
{
impl->disconnect(group);
}
// Emit the signal
result_type operator()(BOOST_SIGNALS_PARMS);
result_type operator()(BOOST_SIGNALS_PARMS) const;
private:
Combiner combiner;
};
template<
typename R,
BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Combiner,
typename Group,
typename GroupCompare,
typename SlotFunction
>
signals::connection
BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction
>::connect(const slot_type& in_slot)
{
// If the slot has been disconnected, just return a disconnected
// connection
if (!in_slot.is_active()) {
return signals::connection();
}
return impl->connect_slot(in_slot.get_slot_function(),
any(),
in_slot.get_bound_objects());
}
template<
typename R,
BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Combiner,
typename Group,
typename GroupCompare,
typename SlotFunction
>
signals::connection
BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction
>::connect(const group_type& group,
const slot_type& in_slot)
{
return impl->connect_slot(in_slot.get_slot_function(),
group,
in_slot.get_bound_objects());
}
template<
typename R,
BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Combiner,
typename Group,
typename GroupCompare,
typename SlotFunction
>
typename BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction>::result_type
BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction
>::operator()(BOOST_SIGNALS_PARMS)
{
// Notify the slot handling code that we are making a call
signals::detail::call_notification notification(this->impl);
// Construct a function object that will call the underlying slots
// with the given arguments.
#if BOOST_SIGNALS_NUM_ARGS == 0
BOOST_SIGNALS_ARGS_STRUCT_INST args;
#else
BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
#endif // BOOST_SIGNALS_NUM_ARGS > 0
call_bound_slot f(&args);
// Let the combiner call the slots via a pair of input iterators
return combiner(signals::detail::make_slot_call_iterator(
notification.impl->slots.begin(), impl->slots.end(), f),
signals::detail::make_slot_call_iterator(
notification.impl->slots.end(), impl->slots.end(), f));
}
template<
typename R,
BOOST_SIGNALS_TEMPLATE_PARMS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
typename Combiner,
typename Group,
typename GroupCompare,
typename SlotFunction
>
typename BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction>::result_type
BOOST_SIGNALS_SIGNAL<
R, BOOST_SIGNALS_TEMPLATE_ARGS
BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS
Combiner, Group, GroupCompare, SlotFunction
>::operator()(BOOST_SIGNALS_PARMS) const
{
// Notify the slot handling code that we are making a call
signals::detail::call_notification notification(this->impl);
// Construct a function object that will call the underlying slots
// with the given arguments.
#if BOOST_SIGNALS_NUM_ARGS == 0
BOOST_SIGNALS_ARGS_STRUCT_INST args;
#else
BOOST_SIGNALS_ARGS_STRUCT_INST args(BOOST_SIGNALS_ARGS);
#endif // BOOST_SIGNALS_NUM_ARGS > 0
call_bound_slot f(&args);
// Let the combiner call the slots via a pair of input iterators
return combiner(signals::detail::make_slot_call_iterator(
notification.impl->slots.begin(), impl->slots.end(), f),
signals::detail::make_slot_call_iterator(
notification.impl->slots.end(), impl->slots.end(), f));
}
} // namespace boost
#undef BOOST_SIGNAL_FUNCTION_N_HEADER
#undef BOOST_SIGNALS_ARGS_STRUCT_INST
#undef BOOST_SIGNALS_CALL_BOUND
#undef BOOST_SIGNALS_ARGS_STRUCT
#undef BOOST_SIGNALS_FUNCTION
#undef BOOST_SIGNALS_SIGNAL
#undef BOOST_SIGNALS_COMMA_IF_NONZERO_ARGS

View File

@@ -0,0 +1,132 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_SLOT_HEADER
#define BOOST_SIGNALS_SLOT_HEADER
#include <boost/signals/detail/signals_common.hpp>
#include <boost/signals/connection.hpp>
#include <boost/signals/trackable.hpp>
#include <boost/visit_each.hpp>
#include <cassert>
namespace boost {
namespace signals {
namespace detail {
class slot_base {
// We would have to enumerate all of the signalN classes here as
// friends to make this private (as it otherwise should be). We can't
// name all of them because we don't know how many there are.
public:
// Get the set of bound objects
std::vector<const trackable*>& get_bound_objects() const
{ return bound_objects; }
// Determine if this slot is still "active", i.e., all of the bound
// objects still exist
bool is_active() const { return watch_bound_objects.connected(); }
protected:
// Create a connection for this slot
void create_connection();
// Get the slot so that it can be copied
template<typename F>
reference_wrapper<const F>
get_invocable_slot(const F& f, signals::detail::signal_tag)
{ return reference_wrapper<const F>(f); }
template<typename F>
const F& get_invocable_slot(const F& f, signals::detail::reference_tag)
{ return f; }
template<typename F>
const F& get_invocable_slot(const F& f, signals::detail::value_tag)
{ return f; }
// Get the slot so that it can be inspected for trackable objects
template<typename F>
const F& get_inspectable_slot(const F& f,
signals::detail::signal_tag)
{ return f; }
template<typename F>
const F& get_inspectable_slot(const F& f,
signals::detail::reference_tag)
{ return f.get(); }
template<typename F>
const F& get_inspectable_slot(const F& f, signals::detail::value_tag)
{ return f; }
// Determines the type of the slot - is it a signal, a reference to a
// slot or just a normal slot.
template<typename F>
typename signals::detail::get_slot_tag<F>::type
tag_type(const F&)
{
typename signals::detail::get_slot_tag<F>::type tag;
return tag;
}
mutable std::vector<const trackable*> bound_objects;
connection watch_bound_objects;
private:
static void bound_object_destructed(void*, void*) {}
};
} // end namespace detail
} // end namespace signals
template<typename SlotFunction>
class slot : public signals::detail::slot_base {
public:
template<typename F>
slot(const F& f) : slot_function(get_invocable_slot(f, tag_type(f)))
{
// Visit each of the bound objects and store them for later use
// An exception thrown here will allow the basic_connection to be
// destroyed when this goes out of scope, and no other connections
// have been made.
signals::detail::bound_objects_visitor do_bind(bound_objects);
visit_each(do_bind, get_inspectable_slot(f, tag_type(f)));
create_connection();
}
#ifdef __BORLANDC__
template<typename F>
slot(F* f) : slot_function(f)
{
create_connection();
}
#endif // __BORLANDC__
// We would have to enumerate all of the signalN classes here as friends
// to make this private (as it otherwise should be). We can't name all of
// them because we don't know how many there are.
public:
// Get the slot function to call the actual slot
const SlotFunction& get_slot_function() const { return slot_function; }
private:
slot(); // no default constructor
slot& operator=(const slot&); // no assignment operator
SlotFunction slot_function;
};
} // end namespace boost
#endif // BOOST_SIGNALS_SLOT_HEADER

View File

@@ -0,0 +1,109 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#ifndef BOOST_SIGNALS_TRACKABLE_HPP
#define BOOST_SIGNALS_TRACKABLE_HPP
#include <boost/type_traits.hpp>
#include <boost/signals/connection.hpp>
#include <boost/ref.hpp>
#include <list>
#include <vector>
namespace boost {
namespace signals {
// Base class for "trackable" objects that can be tracked when they are
// bound in slot target functions. When a trackable object is destroyed,
// the signal/slot connections are disconnected automatically.
class trackable {
private:
static void signal_disconnected(void* obj, void* data);
friend class detail::signal_base_impl;
friend class detail::slot_base;
void signal_connected(connection, signals::detail::bound_object&) const;
protected:
trackable() : connected_signals(), dying(false) {}
trackable(const trackable&) : connected_signals(), dying(false) {}
~trackable();
trackable& operator=(const trackable&)
{
connected_signals.clear();
return *this;
}
private:
typedef std::list<connection> connection_list;
typedef connection_list::iterator connection_iterator;
// List of connections that this object is part of
mutable connection_list connected_signals;
// True when the object is being destroyed
mutable bool dying;
};
namespace detail {
template<bool Cond> struct truth {};
// A visitor that adds each trackable object to a vector
class bound_objects_visitor {
public:
bound_objects_visitor(std::vector<const trackable*>& v) :
bound_objects(v)
{
}
template<typename T>
inline void operator()(const T& t) const
{
visit(t, truth<is_convertible<T, trackable*>::value>());
visit(&t, truth<is_convertible<T*, trackable*>::value>());
}
template<typename T>
inline void operator()(const boost::reference_wrapper<T>& r) const
{
(*this)(r.get());
}
inline void operator()(const trackable* b) const
{
if (b) {
bound_objects.push_back(b);
}
}
private:
template<typename T>
inline void visit(const T&, truth<false>) const
{
}
template<typename T>
inline void visit(const T& t, truth<true>) const
{
(*this)(static_cast<const trackable*>(t));
}
mutable std::vector<const trackable*>& bound_objects;
};
} // end namespace detail
} // end namespace signals
}
#endif // BOOST_SIGNALS_TRACKABLE_HPP

53
src/connection.cpp Normal file
View File

@@ -0,0 +1,53 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signals/connection.hpp>
#include <cassert>
namespace boost {
namespace signals {
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<signals::detail::bound_object>::iterator iterator;
for (iterator i = local_con->bound_objects.begin();
i != local_con->bound_objects.end(); ++i) {
assert(i->disconnect);
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::signals::detail::bound_object>;
#endif

236
src/signal_base.cpp Normal file
View File

@@ -0,0 +1,236 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signals/detail/signal_base.hpp>
#include <cassert>
namespace boost {
namespace signals {
namespace detail {
signal_base_impl::signal_base_impl(const compare_type& comp) :
call_depth(0),
slots(comp)
{
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 (slot_iterator i = slots.begin(); i != slots.end(); ++i) {
i->second.first.disconnect();
}
}
}
connection
signal_base_impl::
connect_slot(const any& slot,
const any& name,
const std::vector<const trackable*>& bound_objects)
{
// Allocate storage for a new basic_connection object to represent the
// connection
basic_connection* con = new basic_connection();
// Create a new connection handle object and place the basic_connection
// object we just created under its control. Note that the "reset"
// routine will delete con if allocation throws.
connection slot_connection;
slot_connection.reset(con);
// 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<slot_iterator> saved_iter(new slot_iterator());
// Add the slot to the list.
slot_iterator pos =
slots.insert(stored_slot_type(name,
connection_slot_pair(slot_connection,
slot)));
// Make the copy of the connection in the list disconnect when it is
// destroyed
pos->second.first.set_controlling();
// 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
con->signal = this;
con->signal_data = saved_iter.release();
con->signal_disconnect = &signal_base_impl::slot_disconnected;
// If an exception is thrown the connection will automatically be
// disconnected.
scoped_connection safe_connection = slot_connection;
// Connect each of the bound objects
for(std::vector<const trackable*>::const_iterator i =
bound_objects.begin();
i != bound_objects.end();
++i) {
// Notify the object that the signal is connecting to it by passing
// it a copy of the connection. If the connection
// should throw, the scoped connection safe_connection will
// disconnect the connection completely.
bound_object binding;
(*i)->signal_connected(slot_connection, 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
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, and we must not
// disconnect the connection now
safe_connection.release();
return slot_connection;
}
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 (slot_iterator i = slots.begin(); i != slots.end(); ++i) {
if (i->second.first.connected())
return false;
}
return true;
}
void signal_base_impl::disconnect(const any& group)
{
std::pair<slot_iterator, slot_iterator> group_slots =
slots.equal_range(group);
while (group_slots.first != group_slots.second) {
slot_iterator next = group_slots.first;
++next;
group_slots.first->second.first.disconnect();
group_slots.first = next;
}
}
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<slot_iterator> slot(
reinterpret_cast<slot_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
{
// Remove any disconnected slots
for (slot_iterator i = slots.begin(); i != slots.end(); /* none */) {
if (!i->second.first.connected())
slots.erase(i++);
else
++i;
}
}
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()
{
}
} // namespace detail
} // namespace signals
} // namespace boost
#ifndef BOOST_MSVC
// Explicit instantiations to keep in the library
template class boost::function2<bool, boost::any, boost::any>;
template class std::multimap<boost::any,
boost::signals::detail::connection_slot_pair,
boost::function2<bool, boost::any, boost::any> >;
#endif

70
src/slot.cpp Normal file
View File

@@ -0,0 +1,70 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signals/slot.hpp>
namespace boost {
namespace signals {
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->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
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(watch_bound_objects);
// Now notify each of the bound objects that they are connected to this
// slot.
for(std::vector<const trackable*>::iterator i = bound_objects.begin();
i != bound_objects.end(); ++i) {
// Notify the object that the slot is connecting to it
signals::detail::bound_object binding;
(*i)->signal_connected(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
signals::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();
}
} // end namespace detail
} // end namespace signals
} // end namespace boost

63
src/trackable.cpp Normal file
View File

@@ -0,0 +1,63 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signals/trackable.hpp>
#include <algorithm>
namespace boost {
namespace signals {
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,
signals::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 signals
}
#ifndef BOOST_MSVC
// Explicit instantiations to keep in the library
template class std::list<boost::signals::connection>;
#endif

37
test/Jamfile Normal file
View File

@@ -0,0 +1,37 @@
subproject libs/signals/test ;
exe signal_n_test : <lib>../build/boost_signals
signal_n_test.cpp
: <include>$(BOOST_ROOT)
;
exe signal_test : <lib>../build/boost_signals
signal_test.cpp
: <include>$(BOOST_ROOT)
;
exe deletion_test : <lib>../build/boost_signals
deletion_test.cpp
: <include>$(BOOST_ROOT)
;
exe trackable_test : <lib>../build/boost_signals
trackable_test.cpp
: <include>$(BOOST_ROOT)
;
exe random_signal_system : <lib>../build/boost_signals
random_signal_system.cpp
: <include>$(BOOST_ROOT)
;
exe dead_slot_test : <lib>../build/boost_signals
dead_slot_test.cpp
: <include>$(BOOST_ROOT)
;
exe ordering_test : <lib>../build/boost_signals
ordering_test.cpp
: <include>$(BOOST_ROOT)
;

52
test/dead_slot_test.cpp Normal file
View File

@@ -0,0 +1,52 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
typedef boost::signal1<int, int> sig_type;
class with_constant : public boost::signals::trackable {
public:
with_constant(int c) : constant(c) {}
int add(int i) { return i + constant; }
private:
int constant;
};
void do_delayed_connect(with_constant* wc,
sig_type& sig,
sig_type::slot_type slot)
{
// Should invalidate the slot, so that we cannot connect to it
delete wc;
boost::signals::connection c = sig.connect(slot);
BOOST_TEST(!c.connected());
}
int test_main(int, char*[])
{
sig_type s1;
with_constant* wc1 = new with_constant(7);
do_delayed_connect(wc1, s1, boost::bind(&with_constant::add, wc1, _1));
return 0;
}

225
test/deletion_test.cpp Normal file
View File

@@ -0,0 +1,225 @@
// Boost.Signals library
//
// Copyright (C) 2001-2 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <iostream>
#include <string>
static boost::signals::connection connections[5];
static std::string test_output;
struct remove_connection {
explicit remove_connection(int v = 0, int i = -1) : value(v), idx(i) {}
void operator()() const {
if (idx >= 0)
connections[idx].disconnect();
//return value;
std::cout << value << " ";
// test_output.push_back(static_cast<char>(value + '0'));
test_output.insert(test_output.end(), value + '0');
}
int value;
int idx;
};
static void
test_remove_self()
{
boost::signal0<void> s0;
connections[0] = s0.connect(remove_connection(0));
connections[1] = s0.connect(remove_connection(1));
connections[2] = s0.connect(remove_connection(2, 2));
connections[3] = s0.connect(remove_connection(3));
std::cout << "Deleting 2" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "013");
s0.disconnect_all_slots();
BOOST_TEST(s0.empty());
connections[0] = s0.connect(remove_connection(0));
connections[1] = s0.connect(remove_connection(1));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3, 3));
std::cout << "Deleting 3" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "012");
s0.disconnect_all_slots();
BOOST_TEST(s0.empty());
connections[0] = s0.connect(remove_connection(0, 0));
connections[1] = s0.connect(remove_connection(1));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3));
std::cout << "Deleting 0" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "123");
s0.disconnect_all_slots();
BOOST_TEST(s0.empty());
connections[0] = s0.connect(remove_connection(0, 0));
connections[1] = s0.connect(remove_connection(1, 1));
connections[2] = s0.connect(remove_connection(2, 2));
connections[3] = s0.connect(remove_connection(3, 3));
std::cout << "Mass suicide" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "");
}
static void
test_remove_prior()
{
boost::signal0<void> s0;
connections[0] = s0.connect(remove_connection(0));
connections[1] = s0.connect(remove_connection(1, 0));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3));
std::cout << "1 removes 0" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "123");
s0.disconnect_all_slots();
BOOST_TEST(s0.empty());
connections[0] = s0.connect(remove_connection(0));
connections[1] = s0.connect(remove_connection(1));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3, 2));
std::cout << "3 removes 2" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "0123");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "013");
}
static void
test_remove_after()
{
boost::signal0<void> s0;
connections[0] = s0.connect(remove_connection(0, 1));
connections[1] = s0.connect(remove_connection(1));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3));
std::cout << "0 removes 1" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "023");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "023");
s0.disconnect_all_slots();
BOOST_TEST(s0.empty());
connections[0] = s0.connect(remove_connection(0));
connections[1] = s0.connect(remove_connection(1, 3));
connections[2] = s0.connect(remove_connection(2));
connections[3] = s0.connect(remove_connection(3));
std::cout << "1 removes 3" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "012");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "012");
}
static void
test_bloodbath()
{
boost::signal0<void> s0;
connections[0] = s0.connect(remove_connection(0, 1));
connections[1] = s0.connect(remove_connection(1, 1));
connections[2] = s0.connect(remove_connection(2, 0));
connections[3] = s0.connect(remove_connection(3, 2));
std::cout << "0 removes 1, 2 removes 0, 3 removes 2" << std::endl;
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "023");
test_output = "";
s0(); std::cout << std::endl;
BOOST_TEST(test_output == "3");
}
int test_main(int, char* [])
{
test_remove_self();
test_remove_prior();
test_remove_after();
test_bloodbath();
return 0;
}

98
test/ordering_test.cpp Normal file
View File

@@ -0,0 +1,98 @@
// Boost.Signals library
//
// Copyright (C) 2002 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
std::vector<int> valuesOutput;
bool ungrouped1 = false;
bool ungrouped2 = false;
bool ungrouped3 = false;
struct emit_int {
emit_int(int v) : value(v) {}
void operator()() const
{
BOOST_TEST(!ungrouped1 && !ungrouped2 && !ungrouped3);
valuesOutput.push_back(value);
std::cout << value << ' ';
}
private:
int value;
};
struct write_ungrouped1 {
void operator()() const
{
BOOST_TEST(!ungrouped1);
ungrouped1 = true;
std::cout << "(Ungrouped #1)" << ' ';
}
};
struct write_ungrouped2 {
void operator()() const
{
BOOST_TEST(!ungrouped2);
ungrouped2 = true;
std::cout << "(Ungrouped #2)" << ' ';
}
};
struct write_ungrouped3 {
void operator()() const
{
BOOST_TEST(!ungrouped3);
ungrouped3 = true;
std::cout << "(Ungrouped #3)" << ' ';
}
};
int test_main(int, char* [])
{
std::vector<int> sortedValues;
boost::signal0<void> sig;
sig.connect(write_ungrouped1());
for (int i = 0; i < 100; ++i) {
using namespace std;
int v = random() % 100;
sortedValues.push_back(v);
sig.connect(v, emit_int(v));
if (i == 50) {
sig.connect(write_ungrouped2());
}
}
sig.connect(write_ungrouped3());
std::sort(sortedValues.begin(), sortedValues.end());
sig();
std::cout << std::endl;
BOOST_TEST(valuesOutput == sortedValues);
BOOST_TEST(ungrouped1);
BOOST_TEST(ungrouped2);
BOOST_TEST(ungrouped3);
return 0;
}

View File

@@ -0,0 +1,413 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#include <boost/signal.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map.hpp>
#include <boost/random.hpp>
#include <map>
#include <set>
#include <stdlib.h>
#include <time.h>
using namespace boost;
using namespace boost::signals;
struct signal_tag {
typedef vertex_property_tag kind;
};
struct connection_tag {
typedef edge_property_tag kind;
};
typedef signal<void, int, int, double, int&> signal_type;
typedef adjacency_list<listS, listS, directedS,
// Vertex properties
property<signal_tag, signal_type*,
// property<vertex_color_t, default_color_type,
property<vertex_index_t, int> >,
// Edge properties
property<connection_tag, connection,
property<edge_weight_t, int> > >
signal_graph_type;
typedef signal_graph_type::vertex_descriptor vertex_descriptor;
typedef signal_graph_type::edge_descriptor edge_descriptor;
// The signal graph
static signal_graph_type signal_graph;
// Mapping from a signal to its associated vertex descriptor
static std::map<signal_type*, vertex_descriptor> signal_to_descriptor;
// Mapping from a connection to its associated edge descriptor
static std::map<connection, edge_descriptor> connection_to_descriptor;
std::map<signal_type*, int> min_signal_propagate_distance;
void remove_disconnected_connections()
{
// remove disconnected connections
std::map<connection, edge_descriptor>::iterator i =
connection_to_descriptor.begin();
while (i != connection_to_descriptor.end()) {
if (!i->first.connected()) {
connection_to_descriptor.erase(i++);
}
else {
++i;
}
}
}
void remove_signal(signal_type* sig)
{
clear_vertex(signal_to_descriptor[sig], signal_graph);
remove_vertex(signal_to_descriptor[sig], signal_graph);
delete sig;
signal_to_descriptor.erase(sig);
remove_disconnected_connections();
}
void random_remove_signal(minstd_rand& rand_gen);
struct tracking_bridge {
tracking_bridge(signal_type* s, minstd_rand& rg) : sig(s), rand_gen(rg) {}
void operator()(int cur_dist, int max_dist, double deletion_prob,
int& deletions_left) const
{
if (signal_to_descriptor.find(sig) == signal_to_descriptor.end())
return;
++cur_dist;
// Update the directed Bacon distance
if (min_signal_propagate_distance.find(sig) ==
min_signal_propagate_distance.end()) {
min_signal_propagate_distance[sig] = cur_dist;
}
else if (cur_dist < min_signal_propagate_distance[sig]) {
min_signal_propagate_distance[sig] = cur_dist;
}
else if (deletion_prob == 0.0) {
// don't bother calling because we've already found a better route here
return;
}
// Maybe delete the signal
if (uniform_01<minstd_rand>(rand_gen)() < deletion_prob &&
deletions_left-- && signal_to_descriptor.size() > 1) {
random_remove_signal(rand_gen);
}
// propagate the signal
else if (cur_dist < max_dist) {
(*sig)(cur_dist, max_dist, deletion_prob, deletions_left);
}
}
signal_type* sig;
minstd_rand& rand_gen;
};
namespace boost {
template<typename V>
void visit_each(V& v, const tracking_bridge& t, int)
{
v(t);
v(t.sig);
}
}
signal_type* add_signal()
{
signal_type* sig = new signal_type();
vertex_descriptor v = add_vertex(signal_graph);
signal_to_descriptor[sig] = v;
put(signal_tag(), signal_graph, v, sig);
return sig;
}
connection add_connection(signal_type* sig1, signal_type* sig2,
minstd_rand& rand_gen)
{
std::cout << " Adding connection: " << sig1 << " -> " << sig2 << std::endl;
connection c = sig1->connect(tracking_bridge(sig2, rand_gen));
edge_descriptor e =
add_edge(signal_to_descriptor[sig1], signal_to_descriptor[sig2],
signal_graph).first;
connection_to_descriptor[c] = e;
put(connection_tag(), signal_graph, e, c);
put(edge_weight, signal_graph, e, 1);
return c;
}
void remove_connection(connection c)
{
signal_type* sig1 = get(signal_tag(), signal_graph,
source(connection_to_descriptor[c], signal_graph));
signal_type* sig2 = get(signal_tag(), signal_graph,
target(connection_to_descriptor[c], signal_graph));
std::cout << " Removing connection: " << sig1 << " -> " << sig2
<< std::endl;
c.disconnect();
remove_edge(connection_to_descriptor[c], signal_graph);
connection_to_descriptor.erase(c);
}
bool signal_connection_exists(signal_type* sig1, signal_type* sig2,
edge_descriptor& edge_desc)
{
vertex_descriptor source_sig = signal_to_descriptor[sig1];
vertex_descriptor target_sig = signal_to_descriptor[sig2];
signal_graph_type::out_edge_iterator e;
for (e = out_edges(source_sig, signal_graph).first;
e != out_edges(source_sig, signal_graph).second; ++e) {
if (target(*e, signal_graph) == target_sig) {
edge_desc = *e;
return true;
}
}
return false;
}
bool signal_connection_exists(signal_type* sig1, signal_type* sig2)
{
edge_descriptor e;
return signal_connection_exists(sig1, sig2, e);
}
std::map<signal_type*, vertex_descriptor>::iterator
choose_random_signal(minstd_rand& rand_gen)
{
int signal_idx = uniform_int<minstd_rand>(rand_gen,
0, signal_to_descriptor.size() - 1)();
std::map<signal_type*, vertex_descriptor>::iterator result =
signal_to_descriptor.begin();
for(; signal_idx; --signal_idx)
++result;
return result;
}
void random_remove_signal(minstd_rand& rand_gen)
{
std::map<signal_type*, vertex_descriptor>::iterator victim =
choose_random_signal(rand_gen);
std::cout << " Removing signal " << victim->first << std::endl;
remove_signal(victim->first);
}
void random_add_connection(minstd_rand& rand_gen)
{
std::map<signal_type*, vertex_descriptor>::iterator source;
std::map<signal_type*, vertex_descriptor>::iterator target;
do {
source = choose_random_signal(rand_gen);
target = choose_random_signal(rand_gen);
} while (signal_connection_exists(source->first, target->first));
add_connection(source->first, target->first, rand_gen);
}
void random_remove_connection(minstd_rand& rand_gen)
{
int victim_idx =
uniform_int<minstd_rand>(rand_gen, 0, num_edges(signal_graph)-1)();
signal_graph_type::edge_iterator e = edges(signal_graph).first;
while (victim_idx--) {
++e;
}
remove_connection(get(connection_tag(), signal_graph, *e));
}
void random_bacon_test(minstd_rand& rand_gen)
{
signal_type* kevin = choose_random_signal(rand_gen)->first;
min_signal_propagate_distance.clear();
min_signal_propagate_distance[kevin] = 0;
const int horizon = 10; // only go to depth 10 at most
std::cout << " Bacon test: kevin is " << kevin
<< "\n Propagating signal...";
// Propagate the signal out to the horizon
int deletions_left = 0;
(*kevin)(0, horizon, 0.0, deletions_left);
std::cout << "OK\n Finding shortest paths...";
// Initialize all colors to white
{
unsigned int num = 0;
for (signal_graph_type::vertex_iterator v = vertices(signal_graph).first;
v != vertices(signal_graph).second;
++v) {
// put(vertex_color, signal_graph, *v, white_color);
put(vertex_index, signal_graph, *v, num++);
}
assert(num == num_vertices(signal_graph));
}
// Perform a breadth-first search starting at kevin, and record the
// distances from kevin to each reachable node.
std::map<vertex_descriptor, int> bacon_distance_map;
#if 0
bacon_distance_map[signal_to_descriptor[kevin]] = 0;
breadth_first_visit(signal_graph, signal_to_descriptor[kevin],
visitor(
make_bfs_visitor(
record_distances(
make_assoc_property_map(bacon_distance_map),
on_examine_edge()))).
color_map(get(vertex_color, signal_graph)));
#endif
dijkstra_shortest_paths(signal_graph, signal_to_descriptor[kevin],
distance_map(make_assoc_property_map(bacon_distance_map)));
std::cout << "OK\n";
// Make sure the bacon distances agree (prior to the horizon)
{
std::map<signal_type*, int>::iterator i;
for (i = min_signal_propagate_distance.begin();
i != min_signal_propagate_distance.end();
++i) {
if (i->second != bacon_distance_map[signal_to_descriptor[i->first]]) {
std::cout << "Signal distance to " << i->first << " was "
<< i->second << std::endl;
std::cout << "Graph distance was "
<< bacon_distance_map[signal_to_descriptor[i->first]]
<< std::endl;
}
assert(i->second == bacon_distance_map[signal_to_descriptor[i->first]]);
}
}
}
void randomly_create_connections(minstd_rand& rand_gen, double edge_probability)
{
// Randomly create connections
uniform_01<minstd_rand> random(rand_gen);
for (signal_graph_type::vertex_iterator v1 = vertices(signal_graph).first;
v1 != vertices(signal_graph).second; ++v1) {
for (signal_graph_type::vertex_iterator v2 = vertices(signal_graph).first;
v2 != vertices(signal_graph).second; ++v2) {
if (random() < edge_probability) {
add_connection(get(signal_tag(), signal_graph, *v1),
get(signal_tag(), signal_graph, *v2),
rand_gen);
}
}
}
}
void random_recursive_deletion(minstd_rand& rand_gen)
{
signal_type* kevin = choose_random_signal(rand_gen)->first;
min_signal_propagate_distance.clear();
min_signal_propagate_distance[kevin] = 0;
const int horizon = 4; // only go to depth "horizon" at most
std::cout << " Recursive deletion test: start is " << kevin << std::endl;
// Propagate the signal out to the horizon
int deletions_left = (int)(0.05*num_vertices(signal_graph));
(*kevin)(0, horizon, 0.05, deletions_left);
}
int main(int argc, char* argv[])
{
if (argc < 4) {
std::cerr << "Usage: random_signal_system <# of initial signals> "
<< "<edge probability> <iterations>" << std::endl;
return 1;
}
int number_of_initial_signals = atoi(argv[1]);
double edge_probability = atof(argv[2]);
int iterations = atoi(argv[3]);
int seed;
if (argc == 5)
seed = atoi(argv[4]);
else
seed = time(0);
std::cout << "Number of initial signals: " << number_of_initial_signals
<< std::endl;
std::cout << "Edge probability: " << edge_probability << std::endl;
std::cout << "Iterations: " << iterations << std::endl;
std::cout << "Seed: " << seed << std::endl;
// Initialize random number generator
minstd_rand rand_gen;
rand_gen.seed(seed);
for (int iter = 0; iter < iterations; ++iter) {
if (num_vertices(signal_graph) < 2) {
for (int i = 0; i < number_of_initial_signals; ++i)
add_signal();
}
while (num_edges(signal_graph) < 2) {
randomly_create_connections(rand_gen, edge_probability);
}
std::cerr << "Iteration #" << (iter+1) << std::endl;
uniform_int<minstd_rand> random_action(rand_gen, 0, 7);
switch (random_action()) {
case 0:
std::cout << " Adding new signal: " << add_signal() << std::endl;
break;
case 1:
random_remove_signal(rand_gen);
break;
case 2:
if (num_edges(signal_graph) <
num_vertices(signal_graph)*num_vertices(signal_graph)) {
random_add_connection(rand_gen);
}
break;
case 3:
random_remove_connection(rand_gen);
break;
case 4:
case 5:
case 6:
random_bacon_test(rand_gen);
break;
case 7:
random_recursive_deletion(rand_gen);
break;
}
}
return 0;
}

164
test/signal_n_test.cpp Normal file
View File

@@ -0,0 +1,164 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <functional>
template<typename T>
struct max_or_default {
typedef T result_type;
template<typename InputIterator>
typename InputIterator::value_type
operator()(InputIterator first, InputIterator last) const
{
if (first == last)
return T();
T max = *first++;
for (; first != last; ++first)
max = (*first > max)? *first : max;
return max;
}
};
struct make_int {
make_int(int n, int cn) : N(n), CN(n) {}
int operator()() { return N; }
int operator()() const { return CN; }
int N;
int CN;
};
template<int N>
struct make_increasing_int {
make_increasing_int() : n(N) {}
int operator()() const { return n++; }
mutable int n;
};
static void
test_zero_args()
{
make_int i42(42, 41);
make_int i2(2, 1);
make_int i72(72, 71);
make_int i63(63, 63);
make_int i62(62, 61);
{
boost::signal0<int, max_or_default<int>, std::string> s0;
boost::signals::connection c2 = s0.connect(i2);
boost::signals::connection c72 = s0.connect("72", i72);
boost::signals::connection c62 = s0.connect("6x", i62);
boost::signals::connection c42 = s0.connect(i42);
BOOST_TEST(s0() == 72);
s0.disconnect("72");
BOOST_TEST(s0() == 62);
c72.disconnect(); // Double-disconnect should be safe
BOOST_TEST(s0() == 62);
s0.disconnect("72"); // Triple-disconect should be safe
BOOST_TEST(s0() == 62);
// Also connect 63 in the same group as 62
s0.connect("6x", i63);
BOOST_TEST(s0() == 63);
// Disconnect all of the 60's
s0.disconnect("6x");
BOOST_TEST(s0() == 42);
c42.disconnect();
BOOST_TEST(s0() == 2);
c2.disconnect();
BOOST_TEST(s0() == 0);
}
{
boost::signal0<int, max_or_default<int> > s0;
boost::signals::connection c2 = s0.connect(i2);
boost::signals::connection c72 = s0.connect(i72);
boost::signals::connection c62 = s0.connect(i62);
boost::signals::connection c42 = s0.connect(i42);
const boost::signal0<int, max_or_default<int> >& cs0 = s0;
BOOST_TEST(cs0() == 72);
}
{
make_increasing_int<7> i7;
make_increasing_int<10> i10;
boost::signal0<int, max_or_default<int> > s0;
boost::signals::connection c7 = s0.connect(i7);
boost::signals::connection c10 = s0.connect(i10);
BOOST_TEST(s0() == 10);
BOOST_TEST(s0() == 11);
}
}
static void
test_one_arg()
{
boost::signal1<int, int, max_or_default<int> > s1;
s1.connect(std::negate<int>());
s1.connect(std::bind1st(std::multiplies<int>(), 2));
BOOST_TEST(s1(1) == 2);
BOOST_TEST(s1(-1) == 1);
}
static void
test_signal_signal_connect()
{
boost::signal1<int, int, max_or_default<int> > s1;
s1.connect(std::negate<int>());
BOOST_TEST(s1(3) == -3);
{
boost::signal1<int, int, max_or_default<int> > s2;
s1.connect(s2);
s2.connect(std::bind1st(std::multiplies<int>(), 2));
s2.connect(std::bind1st(std::multiplies<int>(), -3));
BOOST_TEST(s2(-3) == 9);
BOOST_TEST(s1(3) == 6);
} // s2 goes out of scope and disconnects
BOOST_TEST(s1(3) == -3);
}
int
test_main(int, char* [])
{
test_zero_args();
test_one_arg();
test_signal_signal_connect();
return 0;
}

167
test/signal_test.cpp Normal file
View File

@@ -0,0 +1,167 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <functional>
template<typename T>
struct max_or_default {
typedef T result_type;
template<typename InputIterator>
typename InputIterator::value_type
operator()(InputIterator first, InputIterator last) const
{
if (first == last)
return T();
T max = *first++;
for (; first != last; ++first)
max = (*first > max)? *first : max;
return max;
}
};
struct make_int {
make_int(int n, int cn) : N(n), CN(cn) {}
int operator()() { return N; }
int operator()() const { return CN; }
int N;
int CN;
};
template<int N>
struct make_increasing_int {
make_increasing_int() : n(N) {}
int operator()() const { return n++; }
mutable int n;
};
static void
test_zero_args()
{
make_int i42(42, 41);
make_int i2(2, 1);
make_int i72(72, 71);
make_int i63(63, 63);
make_int i62(62, 61);
{
boost::signal<int>::combiner<max_or_default<int> >::type s0;
std::cout << "sizeof(signal) = " << sizeof(s0) << std::endl;
boost::signals::connection c2 = s0.connect(i2);
boost::signals::connection c72 = s0.connect(72, i72);
boost::signals::connection c62 = s0.connect(60, i62);
boost::signals::connection c42 = s0.connect(i42);
BOOST_TEST(s0() == 72);
s0.disconnect(72);
BOOST_TEST(s0() == 62);
c72.disconnect(); // Double-disconnect should be safe
BOOST_TEST(s0() == 62);
s0.disconnect(72); // Triple-disconect should be safe
BOOST_TEST(s0() == 62);
// Also connect 63 in the same group as 62
s0.connect(60, i63);
BOOST_TEST(s0() == 63);
// Disconnect all of the 60's
s0.disconnect(60);
BOOST_TEST(s0() == 42);
c42.disconnect();
BOOST_TEST(s0() == 2);
c2.disconnect();
BOOST_TEST(s0() == 0);
}
{
boost::signal<int>::combiner<max_or_default<int> >::type s0;
boost::signals::connection c2 = s0.connect(i2);
boost::signals::connection c72 = s0.connect(i72);
boost::signals::connection c62 = s0.connect(i62);
boost::signals::connection c42 = s0.connect(i42);
const boost::signal<int>::combiner<max_or_default<int> >::type& cs0 = s0;
BOOST_TEST(cs0() == 72);
}
{
make_increasing_int<7> i7;
make_increasing_int<10> i10;
boost::signal<int>::combiner<max_or_default<int> >::type s0;
boost::signals::connection c7 = s0.connect(i7);
boost::signals::connection c10 = s0.connect(i10);
BOOST_TEST(s0() == 10);
BOOST_TEST(s0() == 11);
}
}
static void
test_one_arg()
{
boost::signal<int, int>::combiner<max_or_default<int> >::type s1;
s1.connect(std::negate<int>());
s1.connect(std::bind1st(std::multiplies<int>(), 2));
BOOST_TEST(s1(1) == 2);
BOOST_TEST(s1(-1) == 1);
}
static void
test_signal_signal_connect()
{
boost::signal<int, int>::combiner<max_or_default<int> >::type s1;
s1.connect(std::negate<int>());
BOOST_TEST(s1(3) == -3);
{
boost::signal<int, int>::combiner<max_or_default<int> >::type s2;
s1.connect(s2);
s2.connect(std::bind1st(std::multiplies<int>(), 2));
s2.connect(std::bind1st(std::multiplies<int>(), -3));
BOOST_TEST(s2(-3) == 9);
BOOST_TEST(s1(3) == 6);
} // s2 goes out of scope and disconnects
BOOST_TEST(s1(3) == -3);
}
int
test_main(int, char* [])
{
test_zero_args();
test_one_arg();
test_signal_signal_connect();
return 0;
}

72
test/trackable_test.cpp Normal file
View File

@@ -0,0 +1,72 @@
// Boost.Signals library
//
// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// This software is provided "as is" without express or implied warranty,
// and with no claim as to its suitability for any purpose.
// For more information, see http://www.boost.org
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/signal.hpp>
#include <boost/bind.hpp>
struct short_lived : public boost::signals::trackable {
~short_lived() {}
};
struct swallow {
template<typename T> int operator()(const T*, int i) { return i; }
};
template<typename T>
struct max_or_default {
typedef T result_type;
template<typename InputIterator>
T operator()(InputIterator first, InputIterator last) const
{
if (first == last)
return T();
T max = *first++;
for (; first != last; ++first)
max = (*first > max)? *first : max;
return max;
}
};
int test_main(int, char**)
{
typedef boost::signal1<int, int, max_or_default<int> > sig_type;
sig_type s1;
// Test auto-disconnection
BOOST_TEST(s1(5) == 0);
{
short_lived shorty;
s1.connect(boost::bind<int>(swallow(), &shorty, _1));
BOOST_TEST(s1(5) == 5);
}
BOOST_TEST(s1(5) == 0);
// Test auto-disconnection of slot before signal connection
{
short_lived* shorty = new short_lived();
sig_type::slot_type slot(boost::bind<int>(swallow(), shorty, _1));
delete shorty;
BOOST_TEST(s1(5) == 0);
}
return 0;
}