16#include "AUI/Common/ADeque.h"
17#include "AUI/Common/AObject.h"
18#include "AUI/Thread/AMutex.h"
19#include "AAbstractSignal.h"
20#include "AUI/Traits/values.h"
22template<
typename... Args>
28 friend class AWatchable;
30 using func_t = std::function<void(Args...)>;
31 using args_t = std::tuple<Args...>;
38 bool isDisconnected =
false;
43 void invokeSignal(
AObject* emitter,
const std::tuple<Args...>&
args = {});
45 template<
typename Lambda,
typename... A>
46 struct argument_ignore_helper {};
49 template<
typename Lambda>
50 struct argument_ignore_helper<void(Lambda::*)() const>
54 explicit argument_ignore_helper(Lambda l)
59 void operator()(Args...
args) {
64 template<
typename Lambda,
typename A1>
65 struct argument_ignore_helper<void(Lambda::*)(A1) const>
69 explicit argument_ignore_helper(Lambda l)
74 template<
typename... Others>
75 void call(A1&& a1, Others...)
80 void operator()(Args&&...
args) {
81 call(std::move(
args)...);
84 template<
typename Lambda,
typename A1,
typename A2>
85 struct argument_ignore_helper<void(Lambda::*)(A1, A2) const>
89 explicit argument_ignore_helper(Lambda l)
94 template<
typename... Others>
95 void call(A1&& a1, A2&& a2, Others...)
97 l(std::move(a1), std::move(a2));
100 void operator()(Args&&...
args) {
101 call(std::move(
args)...);
105 template<
typename Lambda,
typename A1,
typename A2,
typename A3>
106 struct argument_ignore_helper<void(Lambda::*)(A1, A2, A3) const>
110 explicit argument_ignore_helper(Lambda l)
115 template<
typename... Others>
116 void call(A1&& a1, A2&& a2, A3&& a3, Others...)
118 l(std::move(a1), std::move(a2), std::move<A3>(a3));
121 void operator()(Args&&...
args) {
122 call(std::move(
args)...);
129 template<
class Derived,
class Object,
typename... FArgs>
130 void connect(Derived derived,
void(Object::* memberFunction)(FArgs...))
132 Object*
object =
static_cast<Object*
>(derived);
133 connect(
object, [
object, memberFunction](FArgs...
args)
135 (object->*memberFunction)(args...);
140 template<
class Object,
class Lambda>
141 void connect(Object
object, Lambda lambda)
143 static_assert(std::is_class_v<Lambda>,
"the lambda should be a class");
145 mSlots.push_back(_new<slot>(
slot{ object, argument_ignore_helper<decltype(&Lambda::operator())>(lambda) }));
154 std::tuple<Args...> args;
156 void invokeSignal(
AObject* emitter) {
157 signal.invokeSignal(emitter, std::move(args));
162 return {*
this, std::make_tuple(std::move(
args)...)};
173 unlinkSlot(
slot->object);
182 operator bool()
const {
183 return !mSlots.empty();
186 void clearAllConnections() noexcept
override
188 clearAllConnectionsIf([](
const auto&){
return true; });
192 clearAllConnectionsIf([&](
const _<slot>& p){
return p->object ==
object.ptr(); });
197 return std::any_of(mSlots.begin(), mSlots.end(), [&](
const _<slot>& s) {
198 return s->object == object.ptr();
204 template<
typename Predicate>
205 void clearAllConnectionsIf(Predicate&& predicate)
noexcept {
212 slotsToRemove.reserve(mSlots.size());
213 mSlots.
removeIf([&slotsToRemove, predicate = std::move(predicate)](
const _<slot>& p) {
215 slotsToRemove << std::move(p->func);
221 slotsToRemove.clear();
224#include <AUI/Thread/AThread.h>
226template <
typename ... Args>
234 if (
auto sharedPtr = weakPtrFromObject(emitter).lock()) {
235 emitterPtr = std::move(
static_cast<_<AObject>>(sharedPtr));
238 auto slots = std::move(mSlots);
239 for (
auto i = slots.begin(); i != slots.end();)
242 auto receiverWeakPtr = weakPtrFromObject(
slot.object);
253 if (receiverWeakPtr.lock() !=
nullptr) {
254 slot.object->getThread()->enqueue([
this,
255 receiverWeakPtr = std::move(receiverWeakPtr),
258 if (
slot->isDisconnected) {
261 if (
auto receiverPtr = receiverWeakPtr.lock()) {
262 AAbstractSignal::isDisconnected() = false;
263 (std::apply)(slot->func, args);
264 if (AAbstractSignal::isDisconnected()) {
265 unlinkSlot(receiverPtr.get());
266 slot->isDisconnected = true;
267 mSlots.removeFirst(slot);
276 AAbstractSignal::isDisconnected() =
false;
278 if (
auto sharedPtr = receiverWeakPtr.lock()) {
279 receiverPtr = std::move(sharedPtr);
282 if (!receiverPtr || receiverPtr->isSignalsEnabled()) {
284 if (AAbstractSignal::isDisconnected()) {
285 unlinkSlot(
slot.object);
296 if (mSlots.empty()) {
297 mSlots = std::move(slots);
300 mSlots.insert(mSlots.begin(), std::make_move_iterator(slots.begin()), std::make_move_iterator(slots.end()));
303 AAbstractSignal::isDisconnected() =
false;
313template<
typename... Args>
316#define signals public
Base class for signal.
Definition: AAbstractSignal.h:368
A base object class.
Definition: AObject.h:49
static _< AAbstractThread > current()
Definition: AThread.cpp:221
A std::vector with AUI extensions.
Definition: AVector.h:38
void removeIf(Predicate &&predicate) noexcept
Definition: AVector.h:333
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition: OSAndroid.cpp:29
#define slot(v)
Passes some variable and type of the variable separated by comma. It's convenient to use with the con...
Definition: kAUI.h:90
#define AUI_MARK_AS_USED(variable)
Marks the variable as being used.
Definition: macros.h:50
Definition: ASignal.h:152
Does not allow escaping, allowing to accept lvalue ref, rvalue ref, shared_ptr and etc without overhe...
Definition: values.h:127