5 #ifndef CNOID_UTIL_SIGNAL_H
6 #define CNOID_UTIL_SIGNAL_H
14 namespace signal_private {
19 static_assert(
sizeof( T ) == 0,
"function_traits<T>: T is not a function type");
22 template<
typename R,
typename... Ts>
23 struct function_traits<R(Ts...)>
25 constexpr
static const std::size_t arity =
sizeof...(Ts);
26 using result_type = R;
29 template<
typename R,
typename... Ts>
30 struct function_traits<R(Ts...) const> : function_traits<R(Ts...)> {};
33 template<
class F,
class... Ts,
class... Us>
34 typename std::enable_if<
35 sizeof...(Us) ==
sizeof...(Ts),
36 typename F::result_type>::type
37 apply_impl(F& func, std::tuple<Ts...>&, Us*... us)
42 template<
class F,
class... Ts,
class... Us>
43 typename std::enable_if<
44 sizeof...(Us) <
sizeof...(Ts),
45 typename F::result_type>::type
46 apply_impl(F& func, std::tuple<Ts...>& args, Us*... us)
48 return apply_impl(func, args, us..., &std::get<
sizeof...(Us)>(args));
51 template<
class F,
class... Args>
52 typename F::result_type
53 apply(F& fun, std::tuple<Args...>& args)
55 return apply_impl(fun, args);
61 typedef T result_type;
63 template<
typename InputIterator>
64 T operator()(InputIterator iter, InputIterator last)
const {
78 struct last_value<void> {
80 template<
typename InputIterator>
81 void operator()(InputIterator iter, InputIterator last)
const{
83 if(iter.isReady()) *iter;
90 class SlotHolderBase :
public Referenced
93 SlotHolderBase() : isBlocked(false) { }
94 virtual void disconnect() = 0;
95 virtual bool connected()
const = 0;
96 virtual void changeOrder(
int orderId) = 0;
102 template<
typename SlotHolderType,
typename... Args>
103 class SlotCallIterator
105 typedef typename SlotHolderType::result_type result_type;
118 ref_ptr<SlotHolderType> currentSlotHolder;
120 std::tuple<Args...>& args;
123 void seekActiveSlot(){
124 while(currentSlotHolder && currentSlotHolder->isBlocked){
125 currentSlotHolder = currentSlotHolder->next;
129 SlotCallIterator(SlotHolderType* firstSlot, std::tuple<Args...>& args)
130 : currentSlotHolder(firstSlot), args(args) { }
132 SlotCallIterator(
const SlotCallIterator& org)
133 : currentSlotHolder(org.currentSlotHolder), args(org.args) { }
135 bool operator==(
const SlotCallIterator& rhs)
const {
136 return (currentSlotHolder == rhs.currentSlotHolder);
139 bool operator!=(
const SlotCallIterator& rhs)
const {
140 return (currentSlotHolder != rhs.currentSlotHolder);
143 SlotCallIterator& operator++() {
144 currentSlotHolder = currentSlotHolder->next;
148 bool isReady()
const {
149 return !currentSlotHolder->isBlocked;
152 result_type operator*()
const {
153 return apply(currentSlotHolder->func, args);
162 typename Combiner = signal_private::last_value<
163 typename signal_private::function_traits<TSignature>::result_type>
168 namespace signal_private {
170 template<
typename Signature,
typename Combiner>
171 class SlotHolder :
public SlotHolderBase
174 typedef std::function<Signature> FuncType;
184 typedef typename signal_private::function_traits<Signature>::result_type result_type;
186 SlotHolder(
const FuncType& func)
187 : func(func), prev(nullptr), owner(nullptr) {
190 virtual void disconnect()
override {
191 if(owner) owner->remove(
this);
194 virtual bool connected()
const override {
195 return owner !=
nullptr;
198 virtual void changeOrder(
int orderId)
override {
199 if(owner) owner->changeOrder(
this, orderId);
212 Connection(signal_private::SlotHolderBase* slot) : slot(slot) { }
229 return slot && slot->connected();
234 slot->isBlocked =
true;
240 slot->isBlocked =
false;
245 return slot ? slot->isBlocked :
false;
252 slot->changeOrder(order);
261 : pConnection(&connection) {
265 org.pConnection =
nullptr;
304 template<
typename Combiner,
typename R,
typename... Args>
313 typedef signal_private::SlotHolder<R(Args...), Combiner> SlotHolderType;
317 SlotHolderType* lastSlot;
326 disconnect_all_slots();
331 SlotHolderType* slot =
new SlotHolderType(func);
337 lastSlot->next = slot;
338 slot->prev = lastSlot;
347 if(slot->owner ==
this){
348 SlotHolderType* next = slot->next;
349 SlotHolderType* prev = slot->prev;
360 slot->prev =
nullptr;
361 slot->owner =
nullptr;
362 slot->isBlocked =
true;
373 if(slot->owner ==
this){
375 if(firstSlot != slot){
379 slot->next = firstSlot;
380 slot->next->prev = slot;
385 if(lastSlot != slot){
389 lastSlot->next = slot;
390 slot->prev = lastSlot;
407 return (firstSlot ==
nullptr);
412 auto slot = firstSlot;
421 typedef signal_private::SlotCallIterator<SlotHolderType, Args...> IteratorType;
423 std::tuple<Args...> argset(args...);
424 return combiner(IteratorType(firstSlot, argset), IteratorType(
nullptr, argset));
433 template<
typename InputIterator>
434 bool operator()(InputIterator iter, InputIterator last)
const {
451 template<
typename InputIterator>
452 bool operator()(InputIterator iter, InputIterator last)
const {
467 typename Combiner = signal_private::last_value<
468 typename signal_private::function_traits<Signature>::result_type>
483 return signal->connect(f);