all repos — fluxbox @ 7bca844581a38fbf46f8a3761cbd5e31bd9005d6

custom fork of the fluxbox windowmanager

Prepare the Slot classes to be used independently of Signals

Added some polish around them and, to mark this special occasion, moved them out of the SigImpl
namespace.

PS: This partially reverts commit 0775350fee345e37fb59835dda4d85664346b606, since I had to
reintroduce ReturnType template parameter, because it will be used in other places. But Signal classes
remain without the ReturnType, because I still cannot imagine how would it be used.
Pavel Labath pavelo@centrum.sk
commit

7bca844581a38fbf46f8a3761cbd5e31bd9005d6

parent

0a40d1caf3180538d83c7016939d91c7beaf6c2c

2 files changed, 117 insertions(+), 64 deletions(-)

jump to
M src/FbTk/Signal.hhsrc/FbTk/Signal.hh

@@ -22,6 +22,7 @@

#ifndef FBTK_SIGNAL_HH #define FBTK_SIGNAL_HH +#include "RefCount.hh" #include "Slot.hh" #include <algorithm> #include <list>

@@ -120,66 +121,90 @@ Trackers m_trackers; ///< all instances that tracks this signal.

unsigned m_emitting; }; -template <typename Arg1, typename Arg2, typename Arg3> -class SignalTemplate: public SignalHolder { +} // namespace SigImpl + + +/// Specialization for three arguments. +template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > +class Signal: public SigImpl::SignalHolder { public: - template<typename Functor> - SlotID connect(const Functor& functor) { - return SignalHolder::connect(SlotPtr( new Slot<Arg1, Arg2, Arg3, Functor>(functor) )); - } - -protected: - void emit_(Arg1 arg1, Arg2 arg2, Arg3 arg3) { + void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) { begin_emitting(); for ( Iterator it = begin(); it != end(); ++it ) { if(*it) - static_cast<SigImpl::SlotTemplate<Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3); + static_cast<Slot<void, Arg1, Arg2, Arg3> &>(**it)(arg1, arg2, arg3); } end_emitting(); } -}; -} // namespace SigImpl - - -/// Base template for three arguments. -template <typename Arg1 = SigImpl::EmptyArg, typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg > -class Signal: public SigImpl::SignalTemplate<Arg1, Arg2, Arg3> { -public: - void emit(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { SigImpl::SignalTemplate<Arg1, Arg2, Arg3>::emit_(arg1, arg2, arg3); } + template<typename Functor> + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl<Functor, void, Arg1, Arg2, Arg3>(functor) + )); + } }; /// Specialization for two arguments. template <typename Arg1, typename Arg2> -class Signal<Arg1, Arg2, SigImpl::EmptyArg>: - public SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg> { +class Signal<Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SignalHolder { public: void emit(Arg1 arg1, Arg2 arg2) { - SigImpl::SignalTemplate<Arg1, Arg2, SigImpl::EmptyArg>:: - emit_(arg1, arg2, SigImpl::EmptyArg()); + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast<Slot<void, Arg1, Arg2> &>(**it)(arg1, arg2); + } + end_emitting(); + } + + template<typename Functor> + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl<Functor, void, Arg1, Arg2>(functor) + )); } }; /// Specialization for one argument. template <typename Arg1> -class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: - public SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> { +class Signal<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { public: - void emit(Arg1 arg1) { - SigImpl::SignalTemplate<Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg> - ::emit_(arg1, SigImpl::EmptyArg(), SigImpl::EmptyArg()); + void emit(Arg1 arg) { + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast<Slot<void, Arg1> &>(**it)(arg); + } + end_emitting(); + } + + template<typename Functor> + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl<Functor, void, Arg1>(functor) + )); } }; /// Specialization for no arguments. template <> -class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: - public SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> { +class Signal<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SignalHolder { public: void emit() { - SigImpl::SignalTemplate<SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg> - ::emit_(SigImpl::EmptyArg(), SigImpl::EmptyArg(), SigImpl::EmptyArg()); + begin_emitting(); + for ( Iterator it = begin(); it != end(); ++it ) { + if(*it) + static_cast<Slot<void> &>(**it)(); + } + end_emitting(); + } + + template<typename Functor> + SlotID connect(const Functor& functor) { + return SignalHolder::connect(SlotPtr( + new SlotImpl<Functor, void>(functor) + )); } };
M src/FbTk/Slot.hhsrc/FbTk/Slot.hh

@@ -22,7 +22,7 @@

#ifndef FBTK_SLOT_HH #define FBTK_SLOT_HH -#include "RefCount.hh" +#include "NotCopyable.hh" namespace FbTk {

@@ -31,71 +31,99 @@ namespace SigImpl {

struct EmptyArg {}; -class SlotBase { +/** A base class for all slots. It's purpose is to provide a virtual destructor and to enable the + * Signal class to hold a pointer to a generic slot. + */ +class SlotBase: private FbTk::NotCopyable { public: virtual ~SlotBase() {} }; -template<typename Arg1, typename Arg2, typename Arg3> -class SlotTemplate: public SlotBase { +} // namespace SigImpl + +/** Declares a pure virtual function call operator with a specific number of arguments (depending + * on the template specialization). This allows us to "call" any functor in an opaque way. + */ +template<typename ReturnType, typename Arg1 = SigImpl::EmptyArg, + typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg> +class Slot: public SigImpl::SlotBase { +public: + virtual ReturnType operator()(Arg1, Arg2, Arg3) = 0; +}; + +/// Specialization for two arguments +template<typename ReturnType, typename Arg1, typename Arg2> +class Slot<ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public SigImpl::SlotBase { public: - virtual void operator()(Arg1, Arg2, Arg3) = 0; + virtual ReturnType operator()(Arg1, Arg2) = 0; }; -template<typename Arg1, typename Arg2, typename Arg3, typename Functor> -class Slot: public SlotTemplate<Arg1, Arg2, Arg3> { +/// Specialization for one argument +template<typename ReturnType, typename Arg1> +class Slot<ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase { public: - virtual void operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { m_functor(arg1, arg2, arg3); } + virtual ReturnType operator()(Arg1) = 0; +}; - Slot(Functor functor) : m_functor(functor) {} +/// Specialization for no arguments +template<typename ReturnType> +class Slot<ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public SigImpl::SlotBase { +public: + virtual ReturnType operator()() = 0; +}; + +/** A class which knows how to call a specific functor. It inherits from Slot and implemetents + * the function call operator + */ +template<typename Functor, typename ReturnType, typename Arg1 = SigImpl::EmptyArg, + typename Arg2 = SigImpl::EmptyArg, typename Arg3 = SigImpl::EmptyArg> +class SlotImpl: public Slot<ReturnType, Arg1, Arg2, Arg3> { +public: + virtual ReturnType operator()(Arg1 arg1, Arg2 arg2, Arg3 arg3) + { return m_functor(arg1, arg2, arg3); } + + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for two arguments -template<typename Arg1, typename Arg2, typename Functor> -class Slot<Arg1, Arg2, EmptyArg, Functor>: public SlotTemplate<Arg1, Arg2, EmptyArg> { +/// Specialization for two arguments +template<typename Functor, typename ReturnType, typename Arg1, typename Arg2> +class SlotImpl<Functor, ReturnType, Arg1, Arg2, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1, Arg2> { public: - virtual void operator()(Arg1 arg1, Arg2 arg2, EmptyArg) - { m_functor(arg1, arg2); } + virtual ReturnType operator()(Arg1 arg1, Arg2 arg2) { return m_functor(arg1, arg2); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for one argument -template<typename Arg1, typename Functor> -class Slot<Arg1, EmptyArg, EmptyArg, Functor>: public SlotTemplate<Arg1, EmptyArg, EmptyArg> { +/// Specialization for one argument +template<typename Functor, typename ReturnType, typename Arg1> +class SlotImpl<Functor, ReturnType, Arg1, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType, Arg1> { public: - virtual void operator()(Arg1 arg1, EmptyArg, EmptyArg) - { m_functor(arg1); } + virtual ReturnType operator()(Arg1 arg1) { return m_functor(arg1); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -// specialization for no arguments -template<typename Functor> -class Slot<EmptyArg, EmptyArg, EmptyArg, Functor>: public SlotTemplate<EmptyArg, EmptyArg, EmptyArg> { +/// Specialization for no arguments +template<typename Functor, typename ReturnType> +class SlotImpl<Functor, ReturnType, SigImpl::EmptyArg, SigImpl::EmptyArg, SigImpl::EmptyArg>: public Slot<ReturnType> { public: - virtual void operator()(EmptyArg, EmptyArg, EmptyArg) - { m_functor(); } + virtual ReturnType operator()() { return m_functor(); } - Slot(Functor functor) : m_functor(functor) {} + SlotImpl(Functor functor) : m_functor(functor) {} private: Functor m_functor; }; -} // namespace SigImpl - } // namespace FbTk - #endif // FBTK_SLOT_H