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

Last updated 12 September 2005 21:38:45