Orocos Real-Time Toolkit  2.5.0
signal_template.hpp
00001 /***************************************************************************
00002   tag: Peter Soetens  Wed Jan 18 14:11:38 CET 2006  signal_template.hpp
00003 
00004                         signal_template.hpp -  description
00005                            -------------------
00006     begin                : Wed January 18 2006
00007     copyright            : (C) 2006 Peter Soetens
00008     email                : peter.soetens@mech.kuleuven.be
00009 
00010  ***************************************************************************
00011  *   This library is free software; you can redistribute it and/or         *
00012  *   modify it under the terms of the GNU General Public                   *
00013  *   License as published by the Free Software Foundation;                 *
00014  *   version 2 of the License.                                             *
00015  *                                                                         *
00016  *   As a special exception, you may use this file as part of a free       *
00017  *   software library without restriction.  Specifically, if other files   *
00018  *   instantiate templates or use macros or inline functions from this     *
00019  *   file, or you compile this file and link it with other files to        *
00020  *   produce an executable, this file does not by itself cause the         *
00021  *   resulting executable to be covered by the GNU General Public          *
00022  *   License.  This exception does not however invalidate any other        *
00023  *   reasons why the executable file might be covered by the GNU General   *
00024  *   Public License.                                                       *
00025  *                                                                         *
00026  *   This library is distributed in the hope that it will be useful,       *
00027  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00028  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00029  *   Lesser General Public License for more details.                       *
00030  *                                                                         *
00031  *   You should have received a copy of the GNU General Public             *
00032  *   License along with this library; if not, write to the Free Software   *
00033  *   Foundation, Inc., 59 Temple Place,                                    *
00034  *   Suite 330, Boston, MA  02111-1307  USA                                *
00035  *                                                                         *
00036  ***************************************************************************/
00037 
00038 
00039 
00040 #ifndef OROCOS_SIGNAL_TEMPLATE_HEADER_INCLUDED
00041 #define OROCOS_SIGNAL_TEMPLATE_HEADER_INCLUDED
00042 #include "SignalBase.hpp"
00043 #include "NA.hpp"
00044 
00045 #ifdef ORO_SIGNAL_USE_LIST_LOCK_FREE
00046 #include <boost/lambda/bind.hpp>
00047 #include <boost/bind.hpp>
00048 #include <boost/lambda/casts.hpp>
00049 #else
00050 #include "../os/MutexLock.hpp"
00051 #endif
00052 #endif // !OROCOS_SIGNAL_TEMPLATE_HEADER_INCLUDED
00053 
00054 // Define class names used
00055 #define OROCOS_SIGNAL_N BOOST_JOIN(signal,OROCOS_SIGNATURE_NUM_ARGS)
00056 #define OROCOS_SIGNAL_CONNECTION_N BOOST_JOIN(connection,OROCOS_SIGNATURE_NUM_ARGS)
00057 
00058 
00059 namespace RTT {
00060 
00061     namespace internal {
00062 
00063         template<class SlotFunction>
00064         class OROCOS_SIGNAL_CONNECTION_N : public ConnectionBase
00065         {
00066         public:
00067             typedef SlotFunction slot_function;
00068             typedef SlotFunction function_type;
00069             OROCOS_SIGNATURE_TYPEDEFS
00070 
00071             OROCOS_SIGNAL_CONNECTION_N(SignalBase* s, const slot_function& f)
00072                 : ConnectionBase(s), func(f)
00073             {
00074             }
00075 
00076             void emit(OROCOS_SIGNATURE_PARMS)
00077             {
00078                 if (this->mconnected)
00079                     func(OROCOS_SIGNATURE_ARGS);
00080             }
00081         private:
00082             slot_function func;
00083         };
00084 
00085     template<typename R, OROCOS_SIGNATURE_TEMPLATE_PARMS OROCOS_SIGNATURE_COMMA_IF_NONZERO_ARGS
00086              class SlotFunctionT = OROCOS_SIGNATURE_FUNCTION_N< R OROCOS_SIGNATURE_COMMA_IF_NONZERO_ARGS OROCOS_SIGNATURE_TEMPLATE_ARGS> >
00087     class OROCOS_SIGNAL_N
00088         : public SignalBase
00089     {
00090         OROCOS_SIGNAL_N(const OROCOS_SIGNAL_N< R, OROCOS_SIGNATURE_TEMPLATE_ARGS OROCOS_SIGNATURE_COMMA_IF_NONZERO_ARGS SlotFunctionT>& s);
00091 
00092     public:
00093         typedef SlotFunctionT slot_function_type;
00094         typedef OROCOS_SIGNAL_CONNECTION_N<SlotFunctionT> connection_impl;
00095 
00096         typedef R result_type;
00097         OROCOS_SIGNATURE_ARG_TYPES
00098 
00099 #if OROCOS_SIGNATURE_NUM_ARGS == 1
00100         typedef arg1_type first_argument_type;
00101 #endif
00102 #if OROCOS_SIGNATURE_NUM_ARGS == 2
00103         typedef arg1_type first_argument_type;
00104         typedef arg2_type second_argument_type;
00105 #endif
00106     private:
00107 #ifdef ORO_SIGNAL_USE_LIST_LOCK_FREE
00108         // required for GCC 4.0.2
00109         static connection_impl* applyEmit( connection_t c ) {
00110             return static_cast<connection_impl*> (c.get() );
00111         }
00112 #endif
00113     public:
00114         OROCOS_SIGNAL_N()
00115         {
00116         }
00117 
00118         Handle connect(const slot_function_type& f )
00119         {
00120             Handle h = this->setup(f);
00121             h.connect();
00122             return h;
00123         }
00124 
00125         Handle setup(const slot_function_type& f )
00126         {
00127             connection_t conn(
00128                 new connection_impl(this, f) );
00129             this->conn_setup( conn );
00130             return Handle(conn);
00131         }
00132 
00133         R emit(OROCOS_SIGNATURE_PARMS)
00134         {
00135 #ifdef ORO_SIGNAL_USE_LIST_LOCK_FREE
00136             this->emitting = true;
00137 
00138             // this code did initially not work under gcc 4.0/ubuntu breezy.
00139             // connection_t::get() const becomes an undefined symbol.
00140             // works under gcc 3.4
00141             mconnections.apply( boost::lambda::bind(&connection_impl::emit,
00142                                                     boost::lambda::bind( &applyEmit, boost::lambda::_1) // works for any compiler
00143                                                     //not in gcc 4.0.2: boost::lambda::ll_static_cast<connection_impl*>(boost::lambda::bind(&connection_t::get, boost::lambda::_1))
00144 #if OROCOS_SIGNATURE_NUM_ARGS != 0
00145                                                     ,OROCOS_SIGNATURE_ARGS
00146 #endif
00147                                                     ) );
00148             this->emitting = false;
00149 #else
00150             os::MutexLock lock(m);
00151             if (this->emitting)
00152                 return NA<R>::na(); // avoid uglyness : Handlers calling emit.
00153             this->emitting = true;
00154             iterator it = mconnections.begin();
00155             const_iterator end = mconnections.end();
00156             for (; it != end; ++it ) {
00157                 connection_impl* ci = static_cast<connection_impl*>( it->get() );
00158                 if (ci)
00159                     ci->emit(OROCOS_SIGNATURE_ARGS); // this if... race is guarded by the mutex.
00160             }
00161             this->emitting = false;
00162             this->cleanup();
00163 #endif
00164             return NA<R>::na();
00165         }
00166 
00167         R operator()(OROCOS_SIGNATURE_PARMS)
00168         {
00169             return this->emit(OROCOS_SIGNATURE_ARGS);
00170         }
00171 
00172         R fire(OROCOS_SIGNATURE_PARMS)
00173         {
00174             return this->emit(OROCOS_SIGNATURE_ARGS);
00175         }
00176 
00177         virtual int arity() const { return OROCOS_SIGNATURE_NUM_ARGS; }
00178     };
00179 
00180 }} // namespace sigslot
00181 
00182 
00183 #undef OROCOS_SIGNAL_N
00184 #undef OROCOS_SIGNAL_CONNECTION_N
00185