clientproxy.h
00001 /* 00002 * Player - One Hell of a Robot Server 00003 * Copyright (C) 2000-2003 00004 * Brian Gerkey, Kasper Stoy, Richard Vaughan, & Andrew Howard 00005 * 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 */ 00022 00023 /*************************************************************************** 00024 * Desc: Player v2.0 C++ client 00025 * Authors: Brad Kratochvil, Toby Collett 00026 * 00027 * Date: 23 Sep 2005 00028 # CVS: $Id: clientproxy.h,v 1.2.2.2 2006/06/09 18:13:49 gerkey Exp $ 00029 **************************************************************************/ 00030 00031 00032 #ifndef PLAYERCC_CLIENTPROXY_H 00033 #define PLAYERCC_CLIENTPROXY_H 00034 namespace PlayerCc 00035 { 00036 00049 class ClientProxy 00050 { 00051 friend class PlayerClient; 00052 00053 public: 00054 00055 #ifdef HAVE_BOOST_SIGNALS 00058 typedef boost::signals::connection connection_t; 00059 00061 typedef boost::mutex::scoped_lock scoped_lock_t; 00062 00064 typedef boost::signal<void (void)> read_signal_t; 00065 #else 00066 // if we're not using boost, just define them. 00067 typedef int connection_t; 00068 // we redefine boost::mustex::scoped_lock in playerclient.h 00069 typedef boost::mutex::scoped_lock scoped_lock_t; 00070 // if we're not using boost, just define them. 00071 typedef int read_signal_t; 00072 #endif 00073 00074 protected: 00075 00076 // The ClientProxy constructor 00077 // @attention Potected, so it can only be instantiated by other clients 00078 // 00079 // @throw PlayerError Throws a PlayerError if unable to connect to the client 00080 ClientProxy(PlayerClient* aPc, uint aIndex); 00081 00082 // destructor will try to close access to the device 00083 virtual ~ClientProxy(); 00084 00085 // Subscribe to the proxy 00086 // This needs to be defined for every proxy. 00087 // @arg aIndex the index of the devce we want to connect to 00088 00089 // I wish these could be pure virtual, 00090 // but they're used in the constructor/destructor 00091 virtual void Subscribe(uint aIndex) {}; 00092 00093 // Unsubscribe from the proxy 00094 // This needs to be defined for every proxy. 00095 virtual void Unsubscribe() {}; 00096 00097 // The controlling client object. 00098 PlayerClient* mPc; 00099 00100 // A reference to the C client 00101 playerc_client_t* mClient; 00102 00103 // contains convenience information about the device 00104 playerc_device_t *mInfo; 00105 00106 // if set to true, the current data is "fresh" 00107 bool mFresh; 00108 00109 // @brief Get a variable from the client 00110 // All Get functions need to use this when accessing data from the 00111 // c library to make sure the data access is thread safe. 00112 template<typename T> 00113 T GetVar(const T &aV) const 00114 { // these have to be defined here since they're templates 00115 scoped_lock_t lock(mPc->mMutex); 00116 T v = aV; 00117 return v; 00118 } 00119 00120 // @brief Get a variable from the client by reference 00121 // All Get functions need to use this when accessing data from the 00122 // c library to make sure the data access is thread safe. In this 00123 // case, a begin, end, and destination pointer must be given (similar 00124 // to C++ copy). It is up to the user to ensure there is memory 00125 // allocated at aDest. 00126 template<typename T> 00127 void GetVarByRef(const T aBegin, const T aEnd, T aDest) const 00128 { // these have to be defined here since they're templates 00129 scoped_lock_t lock(mPc->mMutex); 00130 std::copy(aBegin, aEnd, aDest); 00131 } 00132 00133 private: 00134 00135 // The last time that data was read by this client in [s]. 00136 double mLastTime; 00137 00138 // A boost::signal which is used for our callbacks. 00139 // The signal will normally be of a type such as: 00140 // - boost::signal<void ()> 00141 // - boost::signal<void (T)> 00142 // where T can be any type. 00143 // 00144 // @attention we currently only use signals that return void because we 00145 // don't have checks to make sure a signal is registered. If an empty 00146 // signal is called: 00147 // 00148 // @attention "Calling the function call operator may invoke undefined 00149 // behavior if no slots are connected to the signal, depending on the 00150 // combiner used. The default combiner is well-defined for zero slots when 00151 // the return type is void but is undefined when the return type is any 00152 // other type (because there is no way to synthesize a return value)." 00153 // 00154 read_signal_t mReadSignal; 00155 00156 // Outputs the signal if there is new data 00157 void ReadSignal(); 00158 00159 public: 00160 00162 bool IsValid() const { return 0!=GetVar(mInfo->datatime); }; 00163 00167 bool IsFresh() const { return GetVar(mFresh); }; 00168 00170 void NotFresh(); 00171 00174 std::string GetDriverName() const { return mInfo->drivername; }; 00175 00177 double GetDataTime() const { return GetVar(mInfo->datatime); }; 00178 00180 double GetElapsedTime() const 00181 { return GetVar(mInfo->datatime) - GetVar(mInfo->lasttime); }; 00182 00184 PlayerClient * GetPlayerClient() const { return mPc;} 00186 uint GetIndex() const { return GetVar(mInfo->addr.index); }; 00187 00189 uint GetInterface() const { return GetVar(mInfo->addr.interf); }; 00190 00192 std::string GetInterfaceStr() const 00193 { return playerc_lookup_name(GetVar(mInfo->addr.interf)); }; 00194 00208 void SetReplaceRule(bool aReplace, 00209 int aType = -1, 00210 int aSubtype = -1); 00211 00216 int HasCapability(uint aType, uint aSubtype); 00217 00220 template<typename T> 00221 connection_t ConnectReadSignal(T aSubscriber) 00222 { 00223 #ifdef HAVE_BOOST_SIGNALS 00224 scoped_lock_t lock(mPc->mMutex); 00225 return mReadSignal.connect(aSubscriber); 00226 #else 00227 return -1; 00228 #endif 00229 } 00230 00232 void DisconnectReadSignal(connection_t aSubscriber) 00233 { 00234 #ifdef HAVE_BOOST_SIGNALS 00235 scoped_lock_t lock(mPc->mMutex); 00236 aSubscriber.disconnect(); 00237 #endif 00238 } 00239 00240 }; 00241 00242 }// namespace 00243 00244 #endif