File: scoped_connection.h

package info (click to toggle)
libsigc%2B%2B-3.0 3.6.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,352 kB
  • sloc: cpp: 6,829; xml: 347; makefile: 197; python: 148; sh: 73
file content (178 lines) | stat: -rw-r--r-- 7,142 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/*
 * Copyright 2023, The libsigc++ Development Team
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 */

#ifndef SIGC_SCOPED_CONNECTION_HPP
#define SIGC_SCOPED_CONNECTION_HPP

#include <sigc++/connection.h>

namespace sigc
{

/** Convenience class for safe disconnection, including automatic disconnection
 * upon destruction.
 *
 * This is a variant of @ref sigc::connection which also disconnect()s the slot
 * automatically when the scoped_connection is destructed or re-assigned. Refer
 * to @ref sigc::connection for full information about the common functionality.
 *
 * You will use sigc::scoped_connection by constructing it from a ‘normal’,
 * unscoped @ref sigc::connection, such as those returned by 
 * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" and
 * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()",
 * thus ‘wrapping’ the connection in a scoped_connection, adding auto-disconnection.
 * It can also be assigned from an unscoped connection, in which case, if there
 * was a previous slot referred to by the scoped connection, it is disconnected.
 *
 * Once a connection is scoped, it canʼt be copied as that would make it unclear
 * which of the copies would hold responsibility to auto-disconnect the slot. It
 * can, however, be moved, so itʼs usable in containers or so ‘ownership’ of the
 * connection/auto-disconnect can be moved to another instance. Moving from the
 * scoped_connection clears its reference to the slot so it wonʼt disconnect it.
 *
 * If you want a reference-counted scoped_connection, wrap in a std::shared_ptr.
 *
 * @code
 * // Automatic disconnection:
 * {
 *   sigc::scoped_connection sconn = sig.connect(&some_function);
 *   // Do stuff that requires the slot to be connected & called.
 * }
 * // The scoped_connection was destroyed, so the slot is no longer connected.
 *
 * // ***
 *
 * // Moving ownership:
 * {
 *   sigc::scoped_connection sconn = sig.connect(&some_function);
 *   // Do stuff that requires the slot to be connected & called.
 *   take_ownership(std::move(sconn)); // Pass by rvalue.
 * }
 * // Now our `sconn` no longer referred to slot, so it did NOT auto-disconnect.
 *
 * // ***
 *
 * // Shared ownership:
 * {
 *   auto shconn = std::make_shared<sigc::scoped_connection>(sig.connect(&some_function));
 *   take_copy(shconn); // Pass by copy/value
 *   // Now we AND take_copy() must destroy our shared_ptr to auto-disconnect().
 * }
 * // take_copy() may still hold a shared_ptr reference, keeping the slot alive.
 * @endcode
 *
 * @ingroup signal
 * @newin{3,6}
 */
struct SIGC_API scoped_connection final
{
  /** Constructs an empty scoped connection object. */
  [[nodiscard]] scoped_connection() noexcept = default;

  /** Constructs a scoped connection object from an unscoped connection object.
   * The source connection still refers to the slot and can manually disconnect.
   * @param c The connection object to make a copy from, whose slot weʼll
   *   automatically disconnect when the scoped_connection object is destroyed.
   */
  [[nodiscard]] scoped_connection(connection c) noexcept;

  /** Overrides this scoped connection object copying an unscoped connection.
   * The current slot, if any, will be disconnect()ed before being replaced.
   * The source connection still refers to the slot and can manually disconnect.
   * @param c The connection object to make a copy from, whose slot weʼll
   *   automatically disconnect when the scoped_connection object is destroyed.
   */
  scoped_connection& operator=(connection c);

  /// scoped_connection canʼt be copied as it would confuse ownership—see intro.
  scoped_connection& operator=(const scoped_connection&) = delete;
  /// scoped_connection canʼt be copied as it would confuse ownership—see intro.
  scoped_connection(const scoped_connection&) = delete;

  /** Constructs a scoped connection object moving an existing one.
   * The source scoped connection will no longer refer to / disconnect the slot.
   * @param sc The scoped connection object to move from.
   */
  scoped_connection(scoped_connection&& sc) noexcept;

  /** Overrides this scoped connection object moving another one.
   * The current slot, if any, will be disconnect()ed before being replaced.
   * The source scoped connection will no longer refer to / disconnect the slot.
   * @param sc The scoped connection object to move from.
   */
  scoped_connection& operator=(scoped_connection&& sc);

  /// Swap two scoped connections.
  friend SIGC_API void swap(scoped_connection& sca, scoped_connection& scb) noexcept;

  /// scoped_connection disconnects the referred slot, if any, upon destruction.
  ~scoped_connection();

  /** Returns whether the connection is still active.
   * @return @p false if the connection is still active.
   */
  [[nodiscard]] bool empty() const noexcept;

  /** Returns whether the connection is still active.
   * @return @p true if the connection is still active.
   */
  [[nodiscard]] bool connected() const noexcept;

  /** Returns whether the connection is blocked.
   * @return @p true if the connection is blocked.
   */
  [[nodiscard]] bool blocked() const noexcept;

  /** Sets or unsets the blocking state of this connection.
   * See slot_base::block() for details.
   * @param should_block Indicates whether the blocking state should be set or unset.
   * @return @p true if the connection has been in blocking state before.
   */
  bool block(bool should_block = true) noexcept;

  /** Unsets the blocking state of this connection.
   * @return @p true if the connection has been in blocking state before.
   */
  bool unblock() noexcept;

  /// Disconnects the referred slot. This will also happen upon destruction.
  void disconnect();

  /** Returns whether the connection is still active.
   * @return @p true if the connection is still active.
   */
  [[nodiscard]] explicit operator bool() const noexcept;

  /** Releases the connection from a scoped connection object.
   * The scoped connection will no longer refer to / disconnect the slot.
   * @return An unscoped connection object referring to the same slot.
   */
  [[nodiscard]] connection release() noexcept;

private:
  sigc::connection conn_;
};

/// Swap two scoped connections.
SIGC_API
void swap(scoped_connection& sca, scoped_connection& scb) noexcept;

} /* namespace sigc */

#endif /* SIGC_SCOPED_CONNECTION_HPP */