1 /// \file 2 /// \brief Contains the definition of the Sharedd_connection_block class. 3 #ifndef SHARED_CONNECTION_BLOCK_HPP 4 #define SHARED_CONNECTION_BLOCK_HPP 5 #include <signals/connection.hpp> 6 7 #include <memory> 8 9 namespace sig { 10 class Connection_impl_base; 11 12 /// \brief Blocks a Signal/Slot Connection. 13 /// 14 /// Any number of Shared_connection_blocks can be built on a single connection, 15 /// when the last block goes out of scope, the connection is unblocked. 16 class Shared_connection_block { 17 public: 18 /// \brief Create a Shared_connection_block from a Connection and a boolean. 19 /// 20 /// Default constructs to blocking an empty Connection. 21 /// \param conn The Connection to be blocked by *this. 22 /// \param initially_block If true, *this blocks the Connection, otherwise 23 /// *this only holds a reference to the Connection and can block the 24 /// Connection at some other time by calling block(). Shared_connection_block(const Connection & conn=Connection{},bool initially_block=true)25 explicit Shared_connection_block(const Connection& conn = Connection{}, 26 bool initially_block = true) 27 : connection_{conn.pimpl_}, blocking_{initially_block} { 28 if (this->active()) { 29 connection_.lock()->add_block(); 30 } 31 } 32 33 /// \brief Creates a copy of \p x, increasing the block count on the 34 /// Connection if \p x is blocking. Shared_connection_block(const Shared_connection_block & x)35 Shared_connection_block(const Shared_connection_block& x) 36 : connection_{x.connection_}, blocking_{x.blocking_} { 37 if (this->active()) { 38 connection_.lock()->add_block(); 39 } 40 } 41 42 /// \brief Reset *this' Connection to point to \p x's Connection. 43 /// 44 /// If *this was blocking, then the block count is decremented on the 45 /// original Connection. If \p x is blocking, then \p x's Connection gets 46 /// an additional block. operator =(const Shared_connection_block & x)47 Shared_connection_block& operator=(const Shared_connection_block& x) { 48 if (this == &x) { 49 return *this; 50 } 51 this->reset(x); 52 return *this; 53 } 54 55 /// \brief Releases this block from the Connection. 56 /// 57 /// Connection may still be blocked by other Shared_connection_block 58 /// objects. ~Shared_connection_block()59 ~Shared_connection_block() { this->unblock(); } 60 61 /// Releases the Connection block. No-op if not currently blocking. unblock()62 void unblock() { 63 if (this->active()) { 64 connection_.lock()->remove_block(); 65 blocking_ = false; 66 } 67 } 68 69 /// Reasserts a block on a Connection. No-op if currently blocking. block()70 void block() { 71 if (!connection_.expired() && !blocking_) { 72 connection_.lock()->add_block(); 73 blocking_ = true; 74 } 75 } 76 77 /// \returns True if *this is currently blocking a Connection, else false. blocking() const78 bool blocking() const { return !connection_.expired() && blocking_; } 79 80 /// \returns The Connection object associated with *this. connection() const81 Connection connection() const { return Connection(connection_); } 82 83 private: 84 // Remove the block to the associated Connection and reset with the contents 85 // of \p x, applying a block to the new Connection if x is blocking. reset(const Shared_connection_block & x)86 void reset(const Shared_connection_block& x) { 87 this->unblock(); 88 connection_ = x.connection_; 89 blocking_ = x.blocking_; 90 if (this->active()) { 91 connection_.lock()->add_block(); 92 } 93 } 94 95 // Return true if the connection pointed to is still alive and *this is 96 // currently blocking. active()97 bool active() { return !connection_.expired() && blocking_; } 98 99 std::weak_ptr<Connection_impl_base> connection_; 100 bool blocking_; 101 }; 102 103 } // namespace sig 104 #endif // SHARED_CONNECTION_BLOCK_HPP 105