Orocos Real-Time Toolkit
2.5.0
|
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