Sirikata
libspace/plugins/prox/CBRLocationServiceCache.hpp
Go to the documentation of this file.
00001 /*  Sirikata
00002  *  CBRLocationServiceCache.hpp
00003  *
00004  *  Copyright (c) 2009, Ewen Cheslack-Postava
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of libprox nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_CBR_LOCATION_SERVICE_CACHE_HPP_
00034 #define _SIRIKATA_CBR_LOCATION_SERVICE_CACHE_HPP_
00035 
00036 #include <sirikata/pintoloc/ExtendedLocationServiceCache.hpp>
00037 #include <prox/base/LocationServiceCache.hpp>
00038 #include <prox/base/ZernikeDescriptor.hpp>
00039 #include <sirikata/space/LocationService.hpp>
00040 #include <boost/thread.hpp>
00041 
00042 namespace Sirikata {
00043 
00044 /* Implementation of LocationServiceCache which serves Prox libraries;
00045  * works by listening for updates from our LocationService.  Note that
00046  * CBR should only be using the LocationServiceListener methods in normal
00047  * operation -- all other threads are to be used by libprox classes and
00048  * will only be accessed in the proximity thread. Therefore, most of the
00049  * work happens in the proximity thread, with the callbacks just storing
00050  * information to be picked up in the next iteration.
00051  */
00052 class CBRLocationServiceCache :
00053         public ExtendedLocationServiceCache,
00054         public LocationServiceListener
00055 {
00056 public:
00057     typedef Prox::LocationUpdateListener<ObjectProxSimulationTraits> LocationUpdateListener;
00058 
00063     CBRLocationServiceCache(Network::IOStrand* strand, LocationService* locservice, bool replicas);
00064     virtual ~CBRLocationServiceCache();
00065 
00066     /* LocationServiceCache members. */
00067     virtual void addPlaceholderImposter(
00068         const ObjectID& id,
00069         const Vector3f& center_offset,
00070         const float32 center_bounds_radius,
00071         const float32 max_size,
00072         const String& zernike,
00073         const String& mesh
00074     );
00075     virtual Iterator startTracking(const ObjectID& id);
00076     virtual void stopTracking(const Iterator& id);
00077     virtual bool startRefcountTracking(const ObjectID& id);
00078     virtual void stopRefcountTracking(const ObjectID& id);
00079 
00080     // ExtendLocationServiceCache
00081     virtual bool tracking(const ObjectID& id);
00082 
00083     virtual TimedMotionVector3f location(const Iterator& id);
00084     virtual Vector3f centerOffset(const Iterator& id);
00085     virtual float32 centerBoundsRadius(const Iterator& id);
00086     virtual float32 maxSize(const Iterator& id);
00087     virtual bool isLocal(const Iterator& id);
00088     Prox::ZernikeDescriptor& zernikeDescriptor(const Iterator& id);
00089     String mesh(const Iterator& id);
00090 
00091     virtual const ObjectReference& iteratorID(const Iterator& id);
00092 
00093     virtual void addUpdateListener(LocationUpdateListener* listener);
00094     virtual void removeUpdateListener(LocationUpdateListener* listener);
00095 
00096     // ExtendLocationServiceCache
00097     // We also provide accessors by ID for Proximity generate results.
00098     TimedMotionVector3f location(const ObjectID& id);
00099     TimedMotionQuaternion orientation(const ObjectID& id);
00100     AggregateBoundingInfo bounds(const ObjectID& id);
00101     Transfer::URI mesh(const ObjectID& id);
00102     String physics(const ObjectID& id);
00103     virtual bool aggregate(const ObjectID& id) { return isAggregate(id); }
00104 
00105     const bool isAggregate(const ObjectID& id);
00106 
00107 
00108     /* LocationServiceListener members. */
00109     virtual void localObjectAdded(const UUID& uuid, bool agg, const TimedMotionVector3f& loc, const TimedMotionQuaternion& orient, const AggregateBoundingInfo& bounds, const String& mesh, const String& physics, const String& zernike);
00110     virtual void localObjectRemoved(const UUID& uuid, bool agg);
00111     virtual void localLocationUpdated(const UUID& uuid, bool agg, const TimedMotionVector3f& newval);
00112     virtual void localOrientationUpdated(const UUID& uuid, bool agg, const TimedMotionQuaternion& newval);
00113     virtual void localBoundsUpdated(const UUID& uuid, bool agg, const AggregateBoundingInfo& newval);
00114     virtual void localMeshUpdated(const UUID& uuid, bool agg, const String& newval);
00115     virtual void localPhysicsUpdated(const UUID& uuid, bool agg, const String& newval);
00116     virtual void replicaObjectAdded(const UUID& uuid, const TimedMotionVector3f& loc, const TimedMotionQuaternion& orient, const AggregateBoundingInfo& bounds, const String& mesh, const String& physics, const String& zernike);
00117     virtual void replicaObjectRemoved(const UUID& uuid);
00118     virtual void replicaLocationUpdated(const UUID& uuid, const TimedMotionVector3f& newval);
00119     virtual void replicaOrientationUpdated(const UUID& uuid, const TimedMotionQuaternion& newval);
00120     virtual void replicaBoundsUpdated(const UUID& uuid, const AggregateBoundingInfo& newval);
00121     virtual void replicaMeshUpdated(const UUID& uuid, const String& newval);
00122     virtual void replicaPhysicsUpdated(const UUID& uuid, const String& newval);
00123 
00124 private:
00125     // Object data is only accessed in the prox thread (by libprox
00126     // and by this class when updates are passed by the main thread).
00127     // Therefore, this data does *NOT* need to be locked for access.
00128     struct ObjectData {
00129         TimedMotionVector3f location;
00130         TimedMotionQuaternion orientation;
00131         AggregateBoundingInfo bounds;
00132         // Whether the object is local or a replica
00133         bool isLocal;
00134         String mesh;
00135         String physics;
00136         Prox::ZernikeDescriptor zernike;
00137         bool exists; // Exists, i.e. xObjectRemoved hasn't been called
00138         int16 tracking; // Ref count to support multiple users
00139         bool isAggregate;
00140     };
00141 
00142 
00143     // These generate and queue up updates from the main thread
00144     void objectAdded(const UUID& uuid, bool islocal, bool agg, const TimedMotionVector3f& loc, const TimedMotionQuaternion& orient, const AggregateBoundingInfo& bounds, const String& mesh, const String& physics, const String& zernike);
00145     void objectRemoved(const UUID& uuid, bool agg);
00146     void locationUpdated(const UUID& uuid, bool agg, const TimedMotionVector3f& newval);
00147     void orientationUpdated(const UUID& uuid, bool agg, const TimedMotionQuaternion& newval);
00148     void boundsUpdated(const UUID& uuid, bool agg, const AggregateBoundingInfo& newval);
00149     void meshUpdated(const UUID& uuid, bool agg, const String& newval);
00150     void physicsUpdated(const UUID& uuid, bool agg, const String& newval);
00151 
00152     // These do the actual work for the LocationServiceListener methods.  Local versions always
00153     // call these, replica versions only call them if replica tracking is
00154     // on. Although we now have to lock in these, we put them on the strand
00155     // instead of processing directly in the methods above so that they don't
00156     // block any other work.
00157     void processObjectAdded(const ObjectReference& uuid, ObjectData data);
00158     void processObjectRemoved(const ObjectReference& uuid, bool agg);
00159     void processLocationUpdated(const ObjectReference& uuid, bool agg, const TimedMotionVector3f& newval);
00160     void processOrientationUpdated(const ObjectReference& uuid, bool agg, const TimedMotionQuaternion& newval);
00161     void processBoundsUpdated(const ObjectReference& uuid, bool agg, const AggregateBoundingInfo& newval);
00162     void processMeshUpdated(const ObjectReference& uuid, bool agg, const String& newval);
00163     void processPhysicsUpdated(const ObjectReference& uuid, bool agg, const String& newval);
00164 
00165 
00166     CBRLocationServiceCache();
00167 
00168     typedef boost::recursive_mutex Mutex;
00169     typedef boost::lock_guard<Mutex> Lock;
00170     // Separate listener list and rest of data. Some callbacks to listeners can
00171     // be expensive and we don't want to lock during these (e.g. connections
00172     // causing insertions with lots of operations and other changes during the
00173     // insertion).
00174     Mutex mListenerMutex;
00175     Mutex mDataMutex;
00176 
00177     Network::IOStrand* mStrand;
00178     LocationService* mLoc;
00179 
00180     typedef std::set<LocationUpdateListener*> ListenerSet;
00181     ListenerSet mListeners;
00182 
00183     typedef std::tr1::unordered_map<ObjectReference, ObjectData, ObjectReference::Hasher> ObjectDataMap;
00184     ObjectDataMap mObjects;
00185     bool mWithReplicas;
00186 
00187     bool tryRemoveObject(ObjectDataMap::iterator& obj_it);
00188 
00189     // Data contained in our Iterators. We maintain both the UUID and the
00190     // iterator because the iterator can become invalidated due to ordering of
00191     // events in the prox thread.
00192     struct IteratorData {
00193         IteratorData(const ObjectReference& _objid, ObjectDataMap::iterator _it)
00194          : objid(_objid), it(_it) {}
00195 
00196         const ObjectReference objid;
00197         ObjectDataMap::iterator it;
00198     };
00199 
00200 };
00201 
00202 } // namespace Sirikata
00203 
00204 #endif //_SIRIKATA_CBR_LOCATION_SERVICE_CACHE_HPP_