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

Slot blocking/unblocking, from Frantz Maerten

[SVN r27439]
This commit is contained in:
Douglas Gregor
2005-02-19 23:44:26 +00:00
parent e37e0630b9
commit 566669b8b2
6 changed files with 94 additions and 14 deletions

View File

@@ -69,6 +69,30 @@
</method>
</method-group>
<method-group name="blocking">
<method name="block">
<type>void</type>
<parameter name="should_block">
<paramtype>bool</paramtype>
<default>true</default>
</parameter>
<requires><simpara><code>connected()</code></simpara></requires>
<postconditions><simpara><code>blocked() == should_block</code></simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<method name="unblock">
<type>void</type>
<requires><simpara><code>connected()</code></simpara></requires>
<postconditions><simpara><code>!blocked()</code></simpara></postconditions>
<throws><simpara>Will not throw.</simpara></throws>
</method>
<method name="blocked" cv="const">
<type>bool</type>
<returns><simpara><code>true</code> if the associated slot is either disconnected or blocked, <code>false</code> otherwise.</simpara></returns>
<throws><simpara>Will not throw.</simpara></throws>
</method>
</method-group>
<method-group name="modifiers">
<method name="swap">
<type>void</type>

View File

@@ -676,6 +676,29 @@ sig(); <emphasis>// Does nothing: there are no connected slots</emphasis>
</programlisting>
</section>
<section><title>Blocking Slots (Beginner)</title>
<para>Slots can be temporarily "blocked", meaning that they will be
ignored when the signal is invoked but have not been disconnected. The
<code><methodname>block</methodname></code> member function
temporarily blocks a slot, which can be unblocked via
<code><methodname>unblock</methodname></code>. Here is an example of
blocking/unblocking slots:</para>
<programlisting>
boost::signals::connection c = sig.<methodname>connect</methodname>(HelloWorld());
sig(); <emphasis>// Prints "Hello, World!"</emphasis>
c.<methodname>block</methodname>(); <emphasis>// block the slot</emphasis>
assert(c.<methodname>blocked</methodname>());
sig(); <emphasis>// No output: the slot is blocked</emphasis>
c.<methodname>unblock</methodname>(); <emphasis>// unblock the slot</emphasis>
sig(); <emphasis>// Prints "Hello, World!"</emphasis>
</programlisting>
</section>
<section><title>Scoped connections (Intermediate)</title>
<para>The <code>boost::signals::scoped_connection</code> class
references a signal/slot connection that will be disconnected when

View File

@@ -53,6 +53,7 @@ namespace boost {
void* signal;
void* signal_data;
void (*signal_disconnect)(void*, void*);
bool blocked_;
std::list<bound_object> bound_objects;
};
@@ -69,6 +70,12 @@ namespace boost {
connection(const connection&);
~connection();
// Block he connection: if the connection is still active, there
// will be no notification
void block(bool should_block = true) { con->blocked_ = should_block; }
void unblock() { con->blocked_ = false; }
bool blocked() const { return !connected() || con->blocked_; }
// Disconnect the signal and slot, if they are connected
void disconnect() const;
@@ -87,11 +94,11 @@ namespace boost {
public: // TBD: CHANGE THIS
// Set whether this connection object is controlling or not
void set_controlling(bool control = true)
void set_controlling(bool control = true)
{ controlling_connection = control; }
shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection>
get_connection() const
get_connection() const
{ return con; }
private:
@@ -162,6 +169,18 @@ namespace boost {
}
};
// Determines if the underlying connection is callable, ie if
// it is connected and not blocked
struct is_callable {
typedef connection_slot_pair argument_type;
typedef bool result_type;
inline bool operator()(const argument_type& c) const
{
return c.first.connected() && !c.first.blocked() ;
}
};
// Autodisconnects the bound object when it is destroyed unless the
// release method is invoked.
class auto_disconnect_bound_object {

View File

@@ -11,7 +11,6 @@
#define BOOST_SIGNALS_SLOT_CALL_ITERATOR
#include <memory>
#include <functional>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/signals/detail/config.hpp>
@@ -49,33 +48,33 @@ namespace boost {
public:
slot_call_iterator(Iterator iter_in, Iterator end_in, Function f,
optional<result_type> &c)
optional<result_type> &c)
: iter(iter_in), end(end_in), f(f), cache(&c)
{
iter = std::find_if(iter, end, std::not1(is_disconnected()));
iter = std::find_if(iter, end, is_callable());
}
typename inherited::reference
dereference() const
{
if (!cache->is_initialized()) {
cache->reset(f(*iter));
}
if (!cache->is_initialized()) {
cache->reset(f(*iter));
}
return cache->get();
}
void increment()
{
iter = std::find_if(++iter, end, std::not1(is_disconnected()));
cache->reset();
iter = std::find_if(++iter, end, is_callable());
cache->reset();
}
bool equal(const slot_call_iterator& other) const
{
iter = std::find_if(iter, end, std::not1(is_disconnected()));
iter = std::find_if(iter, end, is_callable());
other.iter = std::find_if(other.iter, other.end,
std::not1(is_disconnected()));
is_callable());
return iter == other.iter;
}

View File

@@ -24,6 +24,7 @@ namespace boost {
// signal for the connection to be connected.
con->signal = static_cast<void*>(this);
con->signal_data = 0;
con->blocked_ = false ;
con->signal_disconnect = &bound_object_destructed;
}
@@ -38,8 +39,8 @@ namespace boost {
// Now notify each of the bound objects that they are connected to this
// slot.
for(std::vector<const trackable*>::iterator i =
data->bound_objects.begin();
for(std::vector<const trackable*>::iterator i =
data->bound_objects.begin();
i != data->bound_objects.end(); ++i) {
// Notify the object that the slot is connecting to it
BOOST_SIGNALS_NAMESPACE::detail::bound_object binding;

View File

@@ -92,6 +92,20 @@ test_remove_self()
s0(); std::cout << std::endl;
BOOST_CHECK(test_output == "123");
std::cout << "Blocking 2" << std::endl;
connections[2].block();
test_output = "";
s0(); std::cout << std::endl;
BOOST_CHECK(test_output == "13");
std::cout << "Unblocking 2" << std::endl;
connections[2].unblock();
test_output = "";
s0(); std::cout << std::endl;
BOOST_CHECK(test_output == "123");
s0.disconnect_all_slots();
BOOST_CHECK(s0.empty());