61std::weak_ptr<T>
to_weak(std::weak_ptr<T> w) {
66std::weak_ptr<T>
to_weak(std::shared_ptr<T> s) {
81template <
typename,
typename,
typename =
void,
typename =
void>
84template <
typename F,
typename P,
typename... T>
86 void_t<decltype(((*std::declval<P>()).*std::declval<F>())(std::declval<T>()...))>>
89template <
typename F,
typename... T>
91 void_t<decltype(
std::declval<F>()(std::declval<T>()...))>>
95template <
typename T,
typename =
void>
100 decltype(std::declval<T>().lock()),
101 decltype(std::declval<T>().reset())>>
104template <
typename T,
typename =
void>
109 :
is_weak_ptr<decltype(to_weak(std::declval<T>()))> {};
118template <
typename L,
typename... T>
138 bool disconnect() noexcept {
return m_connected.exchange(
false); }
140 bool blocked() const noexcept {
return m_blocked.load(); }
141 void block() noexcept { m_blocked.store(
true); }
142 void unblock() noexcept { m_blocked.store(
false); }
145 std::atomic<bool> m_connected;
146 std::atomic<bool> m_blocked;
163 : m_state{std::move(o.m_state)}
168 m_state.swap(o.m_state);
175 : m_state{std::move(s)}
177 auto d = m_state.lock();
181 void release() noexcept {
182 auto d = m_state.lock();
187 std::weak_ptr<detail::SlotState> m_state;
214 return d && d->connected();
219 return d && d->disconnect();
224 return d && d->blocked();
276 m_state.swap(o.m_state);
289template <
typename...>
292template <
typename... T>
299template <
typename... Args>
308 virtual
void call_slot(Args...) = 0;
310 template <typename... U>
311 void operator()(U && ...u) {
312 if (SlotState::connected() && !SlotState::blocked())
313 call_slot(std::forward<U>(u)...);
319template <
typename,
typename...>
class Slot {};
325template <
typename Func,
typename... Args>
328 template <
typename F>
336 std::decay_t<Func> func;
342template <
typename Func,
typename... Args>
343class Slot<Func, trait::typelist<Connection&, Args...>> :
public SlotBase<Args...> {
345 template <
typename F>
355 std::decay_t<Func> func;
363template <
typename Pmf,
typename Ptr,
typename... Args>
364class Slot<Pmf, Ptr, trait::typelist<Args...>> :
public SlotBase<Args...> {
366 template <
typename F,
typename P>
368 : pmf{
std::forward<
F>(f)},
369 ptr{
std::forward<P>(p)} {}
372 ((*ptr).*pmf)(args...);
376 std::decay_t<Pmf> pmf;
377 std::decay_t<Ptr>
ptr;
383template <
typename Pmf,
typename Ptr,
typename... Args>
384class Slot<Pmf, Ptr, trait::typelist<Connection&, Args...>> :
public SlotBase<Args...> {
386 template <
typename F,
typename P>
388 : pmf{
std::forward<
F>(f)},
389 ptr{
std::forward<P>(p)} {}
392 ((*ptr).*pmf)(conn, args...);
398 std::decay_t<Pmf> pmf;
399 std::decay_t<Ptr>
ptr;
409template <
typename Func,
typename WeakPtr,
typename... Args>
412 template <
typename F,
typename P>
414 : func{
std::forward<
F>(f)},
419 if (! SlotState::connected())
422 SlotState::disconnect();
428 std::decay_t<Func> func;
429 std::decay_t<WeakPtr>
ptr;
439template <
typename Pmf,
typename WeakPtr,
typename... Args>
442 template <
typename F,
typename P>
444 : pmf{
std::forward<
F>(f)},
449 if (! SlotState::connected())
451 auto sp =
ptr.lock();
453 SlotState::disconnect();
455 ((*sp).*pmf)(args...);
459 std::decay_t<Pmf> pmf;
460 std::decay_t<WeakPtr>
ptr;
494template <
typename Lockable,
typename... T>
496 using lock_type = std::unique_lock<Lockable>;
505 template <
typename... A>
507 SlotPtr *prev =
nullptr;
508 SlotPtr *curr = m_slots ? &m_slots :
nullptr;
512 if ((*curr)->connected()) {
513 if (!m_base.m_block && !(*curr)->blocked())
514 (*curr)->operator()(a...);
516 curr = (*curr)->next ? &((*curr)->next) :
nullptr;
521 (*prev)->next = (*curr)->next;
522 curr = (*prev)->next ? &((*prev)->next) :
nullptr;
525 curr = (*curr)->next ? &((*curr)->next) :
nullptr;
544 : m_block{o.m_block.load()}
546 lock_type lock(o.m_mutex);
551 std::scoped_lock lock(m_mutex, o.m_mutex);
554 m_block.store(o.m_block.exchange(m_block.load()));
570 template <
typename... A>
572 lock_type lock(m_mutex);
573 if (!m_block && m_func) m_func(std::forward<A>(a)...);
585 template <
typename Callable>
588 m_func = std::forward<Callable>(
c);
591 auto s = std::make_shared<slot_t>(std::forward<Callable>(
c));
606 template <
typename Callable>
607 std::enable_if_t<trait::is_callable_v<arg_list, Callable>,
Connection>
610 auto s = std::make_shared<slot_t>(std::forward<Callable>(
c));
624 template <
typename Callable>
625 std::enable_if_t<trait::is_callable_v<ext_arg_list, Callable>,
Connection>
628 auto s = std::make_shared<slot_t>(std::forward<Callable>(
c));
641 template <
typename Pmf,
typename Ptr>
642 std::enable_if_t<trait::is_callable_v<arg_list, Pmf, Ptr> &&
643 !trait::is_weak_ptr_compatible_v<Ptr>,
Connection>
646 auto s = std::make_shared<slot_t>(std::forward<Pmf>(pmf), std::forward<Ptr>(
ptr));
658 template <
typename Pmf,
typename Ptr>
659 std::enable_if_t<trait::is_callable_v<ext_arg_list, Pmf, Ptr> &&
660 !trait::is_weak_ptr_compatible_v<Ptr>,
Connection>
663 auto s = std::make_shared<slot_t>(std::forward<Pmf>(pmf), std::forward<Ptr>(
ptr));
685 template <
typename Pmf,
typename Ptr>
686 std::enable_if_t<!trait::is_callable_v<arg_list, Pmf> &&
687 trait::is_weak_ptr_compatible_v<Ptr>,
Connection>
692 auto s = std::make_shared<slot_t>(std::forward<Pmf>(pmf), w);
713 template <
typename Callable,
typename Trackable>
714 std::enable_if_t<trait::is_callable_v<arg_list, Callable> &&
715 trait::is_weak_ptr_compatible_v<Trackable>,
Connection>
718 auto w =
to_weak(std::forward<Trackable>(
ptr));
720 auto s = std::make_shared<slot_t>(std::forward<Callable>(
c), w);
729 template <
typename... CallArgs>
739 lock_type lock(m_mutex);
756 m_block.store(
false);
763 return m_block.load();
767 template <
typename S>
768 void add_slot(
S &s) {
769 lock_type lock(m_mutex);
772 m_func = CallSlots(*
this);
773 auto slots = m_func.template target<CallSlots>();
774 s->next = slots->m_slots;
776 }
else if (
auto call_slots = m_func.template target<CallSlots>()) {
778 s->next = call_slots->m_slots;
779 call_slots->m_slots = s;
782 using slot_t = detail::Slot<std::function<void(T...)>,
arg_list>;
783 auto s2 = std::make_shared<slot_t>(
784 std::forward<std::function<
void(T...)>>(m_func));
785 m_func = CallSlots(*
this);
786 auto slots = m_func.template target<CallSlots>();
787 s2->next = slots->m_slots;
798 std::function<void(T...)> m_func;
799 mutable Lockable m_mutex;
800 std::atomic<bool> m_block;
808template <
typename... T>
820template <
typename... T>
828template <
typename... T>
ConnectionBlocker is a RAII object that blocks a connection until destruction.
Definition: Signal.h:154
~ConnectionBlocker() noexcept
Definition: Signal.h:157
ConnectionBlocker(const ConnectionBlocker &)=delete
ConnectionBlocker & operator=(const ConnectionBlocker &)=delete
ConnectionBlocker & operator=(ConnectionBlocker &&o) noexcept
Definition: Signal.h:166
ConnectionBlocker()=default
ConnectionBlocker(ConnectionBlocker &&o) noexcept
Definition: Signal.h:162
A Connection object allows interaction with an ongoing slot connection.
Definition: Signal.h:198
void unblock() noexcept
Definition: Signal.h:233
bool connected() const noexcept
Definition: Signal.h:212
ConnectionBlocker blocker() const noexcept
Definition: Signal.h:239
virtual ~Connection()=default
bool blocked() const noexcept
Definition: Signal.h:222
friend class SignalBase
Definition: Signal.h:244
Connection & operator=(const Connection &) noexcept=default
Connection(const Connection &) noexcept=default
void block() noexcept
Definition: Signal.h:227
Connection(std::weak_ptr< detail::SlotState > s) noexcept
Definition: Signal.h:245
std::weak_ptr< detail::SlotState > m_state
Definition: Signal.h:250
bool valid() const noexcept
Definition: Signal.h:208
Connection(Connection &&) noexcept=default
bool disconnect() noexcept
Definition: Signal.h:217
ScopedConnection is a RAII version of Connection It disconnects the slot from the signal upon destruc...
Definition: Signal.h:257
ScopedConnection(ScopedConnection &&o) noexcept
Definition: Signal.h:270
ScopedConnection()=default
ScopedConnection(const ScopedConnection &) noexcept=delete
friend class SignalBase
Definition: Signal.h:281
~ScopedConnection()
Definition: Signal.h:260
ScopedConnection(const Connection &c) noexcept
Definition: Signal.h:264
ScopedConnection & operator=(const ScopedConnection &) noexcept=delete
ScopedConnection(Connection &&c) noexcept
Definition: Signal.h:265
ScopedConnection & operator=(ScopedConnection &&o) noexcept
Definition: Signal.h:274
SignalBase is an implementation of the observer pattern, through the use of an emitting object and sl...
Definition: Signal.h:495
std::enable_if_t< trait::is_callable_v< arg_list, Callable > &&trait::is_weak_ptr_compatible_v< Trackable >, Connection > connect(Callable &&c, Trackable &&ptr)
Overload of connect for lifetime object tracking and automatic disconnection.
Definition: Signal.h:716
std::enable_if_t< trait::is_callable_v< ext_arg_list, Pmf, Ptr > &&!trait::is_weak_ptr_compatible_v< Ptr >, Connection > connect_extended(Pmf &&pmf, Ptr &&ptr)
Overload of connect for pointer over member functions and.
Definition: Signal.h:661
~SignalBase()
Definition: Signal.h:536
void disconnect_all()
Disconnects all the slots Safety: Thread safety depends on locking policy.
Definition: Signal.h:738
std::enable_if_t<!trait::is_callable_v< arg_list, Pmf > &&trait::is_weak_ptr_compatible_v< Ptr >, Connection > connect(Pmf &&pmf, Ptr &&ptr)
Overload of connect for lifetime object tracking and automatic disconnection.
Definition: Signal.h:688
SignalBase() noexcept
Definition: Signal.h:535
bool blocked() const noexcept
Tests blocking state of signal emission.
Definition: Signal.h:762
void block() noexcept
Blocks signal emission Safety: thread safe.
Definition: Signal.h:747
SignalBase & operator=(const SignalBase &)=delete
void unblock() noexcept
Unblocks signal emission Safety: thread safe.
Definition: Signal.h:755
SignalBase(const SignalBase &)=delete
ScopedConnection connect_scoped(CallArgs &&...args)
Creates a connection whose duration is tied to the return object Use the same semantics as connect.
Definition: Signal.h:730
SignalBase & operator=(SignalBase &&o)
Definition: Signal.h:550
trait::typelist< T... > arg_list
Definition: Signal.h:532
std::enable_if_t< trait::is_callable_v< ext_arg_list, Callable >, Connection > connect_extended(Callable &&c)
Connect a callable with an additional Connection argument.
Definition: Signal.h:626
std::enable_if_t< trait::is_callable_v< arg_list, Callable >, Connection > connect_connection(Callable &&c)
Connect a callable of compatible arguments, returning a Connection.
Definition: Signal.h:608
SignalBase(SignalBase &&o)
Definition: Signal.h:543
std::enable_if_t< trait::is_callable_v< arg_list, Pmf, Ptr > &&!trait::is_weak_ptr_compatible_v< Ptr >, Connection > connect(Pmf &&pmf, Ptr &&ptr)
Overload of connect for pointers over member functions.
Definition: Signal.h:644
void connect(Callable &&c)
Connect a callable of compatible arguments.
Definition: Signal.h:586
void operator()(A &&... a) const
Emit a signal.
Definition: Signal.h:571
constexpr Slot(F &&f)
Definition: Signal.h:329
virtual void call_slot(Args ...args) override
Definition: Signal.h:331
virtual void call_slot(Args ...args) override
Definition: Signal.h:348
constexpr Slot(F &&f)
Definition: Signal.h:346
Connection conn
Definition: Signal.h:352
virtual void call_slot(Args ...args) override
Definition: Signal.h:371
constexpr Slot(F &&f, P &&p)
Definition: Signal.h:367
Connection conn
Definition: Signal.h:395
constexpr Slot(F &&f, P &&p)
Definition: Signal.h:387
virtual void call_slot(Args ...args) override
Definition: Signal.h:391
virtual ~SlotBase() noexcept=default
SlotPtr< Args... > next
Definition: Signal.h:316
constexpr SlotPmfTracked(F &&f, P &&p)
Definition: Signal.h:443
virtual void call_slot(Args ...args) override
Definition: Signal.h:448
bool connected() const noexcept
Definition: Signal.h:137
virtual ~SlotState()=default
void unblock() noexcept
Definition: Signal.h:142
bool disconnect() noexcept
Definition: Signal.h:138
void block() noexcept
Definition: Signal.h:141
constexpr SlotState() noexcept
Definition: Signal.h:131
bool blocked() const noexcept
Definition: Signal.h:140
constexpr SlotTracked(F &&f, P &&p)
Definition: Signal.h:413
virtual void call_slot(Args ...args) override
Definition: Signal.h:418
detail namespace with internal helper functions
Definition: xchar.h:20
type
Definition: core.h:556
WPI_BASIC_JSON_TPL_DECLARATION void swap(wpi::WPI_BASIC_JSON_TPL &j1, wpi::WPI_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< wpi::WPI_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< wpi::WPI_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition: json.h:5219
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
cubed< length::millimeter > L
Definition: volume.h:49
std::shared_ptr< SlotBase< T... > > SlotPtr
Definition: Signal.h:293
typename detail::voider< T... >::type void_t
Definition: Signal.h:78
constexpr bool is_callable_v
determine if a type T (Callable or Pmf) is callable with supplied arguments in L
Definition: Signal.h:119
std::weak_ptr< T > to_weak(std::weak_ptr< T > w)
Pointers that can be converted to a weak pointer concept for tracking purpose must implement the to_w...
Definition: Signal.h:61
std::weak_ptr< T > to_weak(std::shared_ptr< T > s)
Definition: Signal.h:66
constexpr bool is_weak_ptr_compatible_v
determine if a pointer is convertible into a "weak" pointer
Definition: Signal.h:115
Definition: ntcore_cpp.h:26
NullMutex(NullMutex &&)=delete
NullMutex operator=(const NullMutex &)=delete
void lock()
Definition: Signal.h:473
NullMutex operator=(NullMutex &&)=delete
bool try_lock()
Definition: Signal.h:472
void unlock()
Definition: Signal.h:474
NullMutex(const NullMutex &)=delete
void type
Definition: Signal.h:74
represent a list of types
Definition: Signal.h:52
::std::recursive_mutex recursive_mutex
Definition: mutex.h:18
::std::mutex mutex
Definition: mutex.h:17
#define S(label, offset, message)
Definition: Errors.h:119