mirror of https://gitee.com/bigwinds/arangodb
185 lines
8.4 KiB
XML
185 lines
8.4 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE section PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN"
|
|
"http://www.boost.org/tools/boostbook/dtd/boostbook.dtd">
|
|
<section last-revision="$Date$">
|
|
<title>Design Overview</title>
|
|
|
|
<using-namespace name="boost"/>
|
|
<using-namespace name="boost::signals"/>
|
|
|
|
<section>
|
|
<title>Type Erasure</title>
|
|
|
|
<para>"Type erasure", where static type information is eliminated
|
|
by the use of dynamically dispatched interfaces, 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 group identifiers 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.</para>
|
|
|
|
<para> To combat this so-called "template bloat", we use
|
|
Boost.Function and Boost.Any to store unknown types and
|
|
operations. Then, all of the code for handling the list of slots
|
|
and the mapping from slot identifiers to connections is factored
|
|
into the class <code><classname>signal_base</classname></code>
|
|
that deals exclusively with the <code>any</code> and
|
|
<code><classname>function</classname></code> objects, hiding the
|
|
actual implementations using the well-known pimpl idiom. The
|
|
actual <code><classname>signalN</classname></code> class templates
|
|
deal only with code that will change depending on the number of
|
|
arguments or which is inherently template-dependent (such as
|
|
connection).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title><code>connection</code> class</title>
|
|
|
|
<para> The <code><classname>connection</classname></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><classname>connection</classname></code> class
|
|
itself is merely a thin wrapper over a
|
|
<code><classname>shared_ptr</classname></code> to a
|
|
<code>basic_connection</code> object.</para>
|
|
|
|
<para> <code><classname>connection</classname></code> objects are
|
|
stored by all participants in the Signals system: each
|
|
<code><classname>trackable</classname></code> object contains a
|
|
list of <code><classname>connection</classname></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 Boost.Function object) and a
|
|
<code><classname>connection</classname></code> object (that will
|
|
disconnect on destruction). Finally, the mapping from slot groups
|
|
to slots is based on the key value in a
|
|
<code><classname>std::multimap</classname></code> (the stored data
|
|
in the <code><classname>std::multimap</classname></code> is the
|
|
slot pair).</para>
|
|
</section>
|
|
|
|
<section>
|
|
<title>Slot Call Iterator</title>
|
|
|
|
<para> 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.</para>
|
|
|
|
<informaltable>
|
|
<tgroup cols="2" align="left">
|
|
<thead>
|
|
<row>
|
|
<entry>Iterator Adaptor</entry>
|
|
<entry>Purpose</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry><para>Slot List Iterator</para></entry>
|
|
<entry><para>An iterator through the list of slots
|
|
connected to a signal. The <code>value_type</code> of this
|
|
iterator will be
|
|
<code><classname>std::pair</classname><any,
|
|
connection></code>, where the
|
|
<code><classname>any</classname></code> contains an
|
|
instance of the slot function type.</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Filter Iterator Adaptor</para></entry>
|
|
<entry><para>This filtering iterator adaptor filters out
|
|
slots that have been disconnected, so we never see a
|
|
disconnected slot in later stages.</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Projection Iterator Adaptor</para></entry>
|
|
<entry><para>The projection iterator adaptor returns a
|
|
reference to the first member of the pair that constitutes
|
|
a connected slot (e.g., just the
|
|
<code><classname>boost::any</classname></code> object that
|
|
holds the slot function).</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Transform Iterator Adaptor</para></entry>
|
|
<entry><para>This transform iterator adaptor performs an
|
|
<code><functionname>any_cast</functionname></code> to
|
|
extract a reference to the slot function with the
|
|
appropriate slot function type.</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Transform Iterator Adaptor</para></entry>
|
|
<entry><para>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.</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Input Caching Iterator Adaptor</para></entry>
|
|
<entry><para>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.</para></entry>
|
|
</row>
|
|
<row>
|
|
<entry><para>Slot Call Iterator</para></entry>
|
|
<entry><para>Iterates over calls to each slot.</para></entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</informaltable>
|
|
</section>
|
|
|
|
<section>
|
|
<title><code>visit_each</code> function template</title>
|
|
|
|
<para> The <code><functionname>visit_each</functionname></code>
|
|
function template is a mechanism for discovering objects that are
|
|
stored within another object. Function template
|
|
<code><functionname>visit_each</functionname></code> takes three
|
|
arguments: an object to explore, a visitor function object that is
|
|
invoked with each subobject, and the <code>int</code> 0. </para>
|
|
|
|
<para> The third parameter is merely a temporary solution to the
|
|
widespread lack of proper function template partial ordering. The
|
|
primary <code><functionname>visit_each</functionname></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<T></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:</para>
|
|
|
|
<programlisting>
|
|
template<typename> class A {};
|
|
template<typename T> void foo(T, long);
|
|
template<typename T> void foo(A<T>, int);
|
|
A<T> at;
|
|
foo(at, 0);
|
|
</programlisting>
|
|
|
|
<para> In this example, we assume that our compiler can not tell
|
|
that <code>A<T></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. </para>
|
|
</section>
|
|
</section>
|