Git-Url: 
http://git.frugalware.org/gitweb/gitweb.cgi?p=pacman-g2.git;a=commitdiff;h=e881fffea89483f51283ca585b913f99d0fc4814

commit e881fffea89483f51283ca585b913f99d0fc4814
Author: Michel Hermier <[email protected]>
Date:   Mon May 19 19:51:54 2014 +0200

libpacman: Add a basic signal slot template class.

diff --git a/lib/libpacman/CMakeLists.txt b/lib/libpacman/CMakeLists.txt
index 9268814..d121e20 100644
--- a/lib/libpacman/CMakeLists.txt
+++ b/lib/libpacman/CMakeLists.txt
@@ -5,6 +5,7 @@ SET(includedir "\${prefix}/include")
CONFIGURE_FILE("pacman.pc.in" "pacman.pc" @ONLY)

set(FLIB_SOURCES
+       kernel/fsignal.h
fstdlib/canonicalize.c
fstring/basename.c
fstring/case.c
diff --git a/lib/libpacman/kernel/fsignal.h b/lib/libpacman/kernel/fsignal.h
new file mode 100644
index 0000000..46e40eb
--- /dev/null
+++ b/lib/libpacman/kernel/fsignal.h
@@ -0,0 +1,260 @@
+/*
+ *  fsignal.h
+ *
+ *  Copyright (c) 2014 by Michel Hermier <[email protected]>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program 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 General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ *  USA.
+ */
+#ifndef FSIGNAL_H
+#define FSIGNAL_H
+
+#include <memory> // For std::unique_ptr
+#include <vector> // For std::vector
+
+#include "util.h" // for ASSERT
+
+namespace flib
+{
+
+template <typename T>
+T fdefault_constructor()
+{
+       return T();
+}
+
+template <typename T>
+struct FAccumulator
+{
+       T value;
+
+       FAccumulator()
+               : value(fdefault_constructor<T>())
+       { }
+
+       template <typename Any>
+       const T &operator += (const Any &any)
+       {
+               return value += any;
+       }
+};
+
+template <>
+struct FAccumulator<void>
+{
+       template <typename Any>
+       void operator += (const Any &any)
+       { }
+};
+
+template <typename>
+class FCallable;
+
+template <typename R, typename... Args>
+struct FCallable<R(Args...)>
+{
+       virtual ~FCallable()
+       { }
+
+       virtual R operator () (Args...) const = 0;
+};
+
+namespace detail
+{
+
+template <typename>
+class FSignalBase;
+
+template <typename R, typename... Args>
+class FSignalBase<R(Args...)>
+{
+protected:
+       std::vector<std::unique_ptr<flib::FCallable<R(Args...)>>> m_connections;
+       typedef typename 
std::vector<std::unique_ptr<flib::FCallable<R(Args...)>>>::value_type 
value_type;
+       typedef typename 
std::vector<std::unique_ptr<flib::FCallable<R(Args...)>>>::const_reference 
const_reference;
+
+       bool connect(FCallable<R(Args...)> *connection)
+       {
+               ASSERT(connection != nullptr, return false);
+               m_connections.push_back(value_type(connection));
+               return true;
+       }
+};
+
+}
+
+template <typename>
+class FSignal;
+
+template <typename R, typename... Args>
+class FSignal<R(Args...)>
+       : protected flib::detail::FSignalBase<R(Args...)>
+{
+       typedef flib::detail::FSignalBase<R(Args...)> super_type;
+       typedef typename super_type::const_reference const_reference;
+
+       template <typename FunctionR, typename... FunctionArgs>
+       struct FFunctionConnection
+               : flib::FCallable<R(Args...)>
+       {
+               typedef FunctionR (*function_type)(FunctionArgs..., ...);
+
+               function_type m_function;
+
+               FFunctionConnection(FunctionR (*function)(FunctionArgs...))
+                       : m_function((function_type)function)
+               { }
+
+               R operator () (Args... args) const
+               {
+                       return m_function(args...);
+               }
+       };
+
+       template <typename Receiver, typename MethodR, typename... MethodArgs>
+       struct FMethodConnection
+               : flib::FCallable<R(Args...)>
+       {
+               typedef MethodR (Receiver::*method_type)(MethodArgs..., ...);
+
+               Receiver *m_receiver;
+               method_type m_method;
+
+               FMethodConnection(Receiver *receiver, MethodR 
(Receiver::*method)(MethodArgs...))
+                       : m_receiver(receiver), m_method((method_type)method)
+               { }
+
+               R operator () (Args... args) const
+               {
+                       return (m_receiver->*m_method)(args...);
+               }
+       };
+
+public:
+       template <typename FunctionR, typename... FunctionArgs>
+       bool connect(FunctionR (*function)(FunctionArgs...))
+       {
+               ASSERT(function != nullptr, return false);
+
+               return super_type::connect(new FFunctionConnection<FunctionR, 
FunctionArgs...>(function));
+       }
+
+       template <typename Receiver, typename MethodR, typename... MethodArgs>
+       bool connect(Receiver *receiver, MethodR 
(Receiver::*method)(MethodArgs...))
+       {
+               ASSERT(receiver != nullptr, return false);
+               ASSERT(receiver != nullptr, return false);
+
+               return super_type::connect(new FMethodConnection<Receiver, 
MethodR, MethodArgs...>(receiver, method));
+       }
+
+       template <typename Acc = flib::FAccumulator<void>>
+       Acc operator () (Args... args) const
+       {
+               Acc accumulator = flib::fdefault_constructor<Acc>();
+
+               for(const_reference callable : super_type::m_connections) {
+                       accumulator += (*callable)(args...);
+               }
+               return accumulator;
+       }
+
+       template <typename Acc = flib::FAccumulator<void>>
+       inline Acc emit(Args... args) const
+       {
+               return operator () <Acc> (args...);
+       }
+};
+
+template <typename... Args>
+class FSignal<void(Args...)>
+       : protected flib::detail::FSignalBase<void(Args...)>
+{
+       typedef flib::detail::FSignalBase<void(Args...)> super_type;
+       typedef typename super_type::const_reference const_reference;
+
+       template <typename FunctionR, typename... FunctionArgs>
+       struct FFunctionConnection
+               : flib::FCallable<void(Args...)>
+       {
+               typedef void (*function_type)(FunctionArgs..., ...);
+
+               function_type m_function;
+
+               FFunctionConnection(FunctionR (*function)(FunctionArgs...))
+                       : m_function((function_type)function)
+               { }
+
+               void operator () (Args... args) const
+               {
+                       m_function(args...);
+               }
+       };
+
+       template <typename Receiver, typename MethodR, typename... MethodArgs>
+       struct FMethodConnection
+               : flib::FCallable<void(Args...)>
+       {
+               typedef void (Receiver::*method_type)(MethodArgs..., ...);
+
+               Receiver *m_receiver;
+               method_type m_method;
+
+               FMethodConnection(Receiver *receiver, MethodR 
(Receiver::*method)(MethodArgs...))
+                       : m_receiver(receiver), m_method((method_type)method)
+               { }
+
+               void operator () (Args... args) const
+               {
+                       (m_receiver->*m_method)(args...);
+               }
+       };
+
+public:
+       template <typename FunctionR, typename... FunctionArgs>
+       bool connect(FunctionR (*function)(FunctionArgs...))
+       {
+               ASSERT(function != nullptr, return false);
+
+               return super_type::connect(new FFunctionConnection<FunctionR, 
FunctionArgs...>(function));
+       }
+
+       template <typename Receiver, typename MethodR, typename... MethodArgs>
+       bool connect(Receiver *receiver, MethodR 
(Receiver::*method)(MethodArgs...))
+       {
+               ASSERT(receiver != nullptr, return false);
+               ASSERT(receiver != nullptr, return false);
+
+               return super_type::connect(new FMethodConnection<Receiver, 
MethodR, MethodArgs...>(receiver, method));
+       }
+
+       void operator () (Args... args) const
+       {
+               for(const_reference callable : super_type::m_connections) {
+                       (*callable)(args...);
+               }
+       }
+
+       inline void emit(Args... args) const
+       {
+               operator () (args...);
+       }
+};
+
+}
+
+#endif /* FSIGNAL_H */
+
+/* vim: set ts=2 sw=2 noet: */
_______________________________________________
Frugalware-git mailing list
[email protected]
http://frugalware.org/mailman/listinfo/frugalware-git

Reply via email to