QtGStreamer  0.10.2
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
emitimpl.h
00001 /*
00002     Copyright (C) 2010 George Kiagiadakis <kiagiadakis.george@gmail.com>
00003     Copyright (C) 2010 Collabora Ltd.
00004       @author George Kiagiadakis <george.kiagiadakis@collabora.co.uk>
00005 
00006     This library is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU Lesser General Public License as published
00008     by the Free Software Foundation; either version 2.1 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU Lesser General Public License for more details.
00015 
00016     You should have received a copy of the GNU Lesser General Public License
00017     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018 */
00019 #if !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING
00020 
00021 # ifndef IN_QGLIB_SIGNAL_H
00022 #  error "This file must not be included directly"
00023 # endif
00024 
00025 # include "value.h"
00026 # include "quark.h"
00027 # include <QtCore/QList>
00028 # include <QtCore/QDebug>
00029 # include <stdexcept>
00030 
00031 
00032 namespace QGlib {
00033 namespace Private {
00034 
00036 QTGLIB_EXPORT Value emit(void *instance, const char *signal, Quark detail, const QList<Value> & args);
00037 
00038 template <typename Signature>
00039 struct EmitImpl {};
00040 
00041 } //namespace Private
00042 } //namespace QGlib
00043 
00044 
00045 # if QGLIB_HAVE_CXX0X
00046 
00047 namespace QGlib {
00048 namespace Private {
00049 
00050 //BEGIN ******** packArguments ********
00051 
00052 inline QList<Value> packArguments()
00053 {
00054     return QList<Value>();
00055 }
00056 
00057 template <typename Arg1, typename... Args>
00058 QList<Value> packArguments(const Arg1 & a1, const Args & ... args)
00059 {
00060     QList<Value> && result = packArguments(args...);
00061     Value v;
00062     v.init<Arg1>();
00063     ValueImpl<Arg1>::set(v, a1);
00064     //prepend, since we are packing from the last to the first argument
00065     result.prepend(v);
00066     return result;
00067 }
00068 
00069 //END ******** packArguments ********
00070 //BEGIN ******** EmitImpl ********
00071 
00072 template <typename R, typename... Args>
00073 struct EmitImpl<R (Args...)>
00074 {
00075     static inline R emit(void *instance, const char *signal, Quark detail, const Args & ... args)
00076     {
00077         try {
00078             Value && returnValue = Private::emit(instance, signal, detail, packArguments(args...));
00079             return ValueImpl<R>::get(returnValue);
00080         } catch(const std::exception & e) {
00081             qCritical() << "Error during emission of signal" << signal << ":" << e.what();
00082             return R();
00083         }
00084     }
00085 };
00086 
00087 template <typename... Args>
00088 struct EmitImpl<void (Args...)>
00089 {
00090     static inline void emit(void *instance, const char *signal, Quark detail, const Args & ... args)
00091     {
00092         try {
00093             Value && returnValue = Private::emit(instance, signal, detail, packArguments(args...));
00094 
00095             if (returnValue.isValid()) {
00096                 qWarning() << "Ignoring return value from emission of signal" << signal;
00097             }
00098         } catch(const std::exception & e) {
00099             qCritical() << "Error during emission of signal" << signal << ":" << e.what();
00100         }
00101     }
00102 };
00103 
00104 //END ******** EmitImpl ********
00105 
00106 } //namespace Private
00107 
00108 //BEGIN ******** QGlib::emit ********
00109 
00110 template <typename R, typename... Args>
00111 R emit(void *instance, const char *detailedSignal, const Args & ... args)
00112 {
00113     return Private::EmitImpl<R (Args...)>::emit(instance, detailedSignal, Quark(), args...);
00114 }
00115 
00116 template <typename R, typename... Args>
00117 R emitWithDetail(void *instance, const char *signal, Quark detail, const Args & ... args)
00118 {
00119     return Private::EmitImpl<R (Args...)>::emit(instance, signal, detail, args...);
00120 }
00121 
00122 //END ******** QGlib::emit ********
00123 
00124 } //namespace QGlib
00125 
00126 # else //QGLIB_HAVE_CXX0X
00127 
00128 #  include <boost/preprocessor.hpp>
00129 
00130 // include the second part of this file as many times as QGLIB_SIGNAL_MAX_ARGS specifies
00131 #  define BOOST_PP_ITERATION_PARAMS_1 (3,(0, QGLIB_SIGNAL_MAX_ARGS, "QGlib/emitimpl.h"))
00132 #  include BOOST_PP_ITERATE()
00133 #  undef BOOST_PP_ITERATION_PARAMS_1
00134 
00135 # endif //QGLIB_HAVE_CXX0X
00136 
00137 
00138 #else // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING
00139 
00140 /*
00141     This part is included from BOOST_PP_ITERATE(). It defines specializations of struct EmitImpl
00142     with different number of arguments as well as the multiple implementations of the non-variadic
00143     QGlib::emit. This part is included multiple times (QGLIB_SIGNAL_MAX_ARGS defines how many),
00144     and each time it defines those classes and functions with different number of arguments.
00145     The concept is based on the implementation of boost::function.
00146 */
00147 
00148 # define QGLIB_SIGNAL_IMPL_NUM_ARGS  \
00149     BOOST_PP_ITERATION()
00150 
00151 # define QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_PARAMS \
00152     BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, typename A)
00153 
00154 # define QGLIB_SIGNAL_IMPL_TEMPLATE_PARAMS \
00155     BOOST_PP_ENUM_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, typename A)
00156 
00157 # define QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_ARGS \
00158     BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, A)
00159 
00160 # define QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS \
00161     BOOST_PP_ENUM_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, A)
00162 
00163 # define QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS \
00164     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, const A, & a)
00165 
00166 # define QGLIB_SIGNAL_IMPL_FUNCTION_ARGS \
00167     BOOST_PP_ENUM_TRAILING_PARAMS(QGLIB_SIGNAL_IMPL_NUM_ARGS, a)
00168 
00169 
00170 namespace QGlib {
00171 namespace Private {
00172 
00173 //BEGIN ******** boostpp EmitImpl ********
00174 
00175 # define QGLIB_SIGNAL_IMPL_PACK_ARGS_STEP(z, n, list) \
00176     { \
00177         Value v; \
00178         v.init<A##n>(); \
00179         ValueImpl<A##n>::set(v, a##n); \
00180         list.append(v); \
00181     }
00182 
00183 # define QGLIB_SIGNAL_IMPL_PACK_ARGS(list) \
00184     BOOST_PP_REPEAT(QGLIB_SIGNAL_IMPL_NUM_ARGS, QGLIB_SIGNAL_IMPL_PACK_ARGS_STEP, list)
00185 
00186 template <typename R QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_PARAMS>
00187 struct EmitImpl<R (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)>
00188 {
00189     static inline R emit(void *instance, const char *signal, Quark detail
00190                          QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS)
00191     {
00192         try {
00193             QList<Value> values;
00194             QGLIB_SIGNAL_IMPL_PACK_ARGS(values)
00195             Value returnValue = Private::emit(instance, signal, detail, values);
00196             return ValueImpl<R>::get(returnValue);
00197         } catch(const std::exception & e) {
00198             qCritical() << "Error during emission of signal" << signal << ":" << e.what();
00199             return R();
00200         }
00201     }
00202 };
00203 
00204 template <QGLIB_SIGNAL_IMPL_TEMPLATE_PARAMS>
00205 struct EmitImpl<void (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)>
00206 {
00207     static inline void emit(void *instance, const char *signal, Quark detail
00208                             QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS)
00209     {
00210         try {
00211             QList<Value> values;
00212             QGLIB_SIGNAL_IMPL_PACK_ARGS(values)
00213             Value returnValue = Private::emit(instance, signal, detail, values);
00214             if (returnValue.isValid()) {
00215                 qWarning() << "Ignoring return value from emission of signal" << signal;
00216             }
00217         } catch(const std::exception & e) {
00218             qCritical() << "Error during emission of signal" << signal << ":" << e.what();
00219         }
00220     }
00221 };
00222 
00223 # undef QGLIB_SIGNAL_IMPL_PACK_ARGS
00224 # undef QGLIB_SIGNAL_IMPL_PACK_ARGS_STEP
00225 
00226 //END ******** boostpp EmitImpl ********
00227 
00228 } //namespace Private
00229 
00230 //BEGIN ******** boostpp QGlib::emit ********
00231 
00232 template <typename R QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_PARAMS>
00233 R emit(void *instance, const char *detailedSignal QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS)
00234 {
00235     return Private::EmitImpl<R (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)>
00236                 ::emit(instance, detailedSignal, Quark() QGLIB_SIGNAL_IMPL_FUNCTION_ARGS);
00237 }
00238 
00239 template <typename R QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_PARAMS>
00240 R emitWithDetail(void *instance, const char *signal, Quark detail QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS)
00241 {
00242     return Private::EmitImpl<R (QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS)>
00243                 ::emit(instance, signal, detail QGLIB_SIGNAL_IMPL_FUNCTION_ARGS);
00244 }
00245 
00246 //END ******** boostpp QGlib::emit ********
00247 
00248 } //namespace QGlib
00249 
00250 # undef QGLIB_SIGNAL_IMPL_FUNCTION_ARGS
00251 # undef QGLIB_SIGNAL_IMPL_FUNCTION_PARAMS
00252 # undef QGLIB_SIGNAL_IMPL_TEMPLATE_ARGS
00253 # undef QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_ARGS
00254 # undef QGLIB_SIGNAL_IMPL_TEMPLATE_PARAMS
00255 # undef QGLIB_SIGNAL_IMPL_TRAILING_TEMPLATE_PARAMS
00256 # undef QGLIB_SIGNAL_IMPL_NUM_ARGS
00257 
00258 #endif // !defined(BOOST_PP_IS_ITERATING) || !BOOST_PP_IS_ITERATING