Homepage Demos Overview Downloads Tutorials Reference
Credits

SharedObject.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_SharedObject_h
00003 #define INCLUDED_SharedObject_h
00004 
00005 #include <OPENR/RCRegion.h>
00006 
00007 //! It's nice to have a parent class of SharedObject (which is what you probably want to be reading) so that you can pass around the data structure without worrying about what type is inside the shared memory region.
00008 /*! See MotionManager for an example on how to use this. */
00009 class SharedObjectBase {
00010 public:
00011   void* data() const { return rcr->Base(); } //!< returns a pointer to the data region
00012   RCRegion * getRegion() const { return rcr; } //!< returns the OPEN-R memory region, should you need it
00013 
00014 protected:
00015   SharedObjectBase() : rcr(NULL) {} //!< constructor, protected because you shouldn't need to create this directly, just a common interface to all templates of SharedObject
00016 
00017   //< destructor, automatically dereferences #rcr
00018   virtual ~SharedObjectBase() {
00019     //std::cout << "~SharedObjectBase(): rcr->NumberOfReference()==" << rcr->NumberOfReference() << std::endl;
00020     if(rcr && rcr->NumberOfReference()>0)
00021       rcr->RemoveReference();
00022     else
00023       std::cout << "WARNING: SharedObjectBase destructed without reference" << std::endl;
00024     //std::cout << "~SharedObjectBase()NOW: rcr->NumberOfReference()==" << rcr->NumberOfReference() << std::endl;
00025   } 
00026   RCRegion * rcr; //!< the pointer to the shared memory region this is in charge of
00027   
00028 private:
00029   SharedObjectBase(const SharedObjectBase&); //!< this shouldn't be called...
00030   SharedObjectBase& operator=(const SharedObjectBase&); //!< this shouldn't be called...
00031 };  
00032 
00033 //! This templated class allows convenient creation of any type of class wrapped in a shared memory region
00034 /*! @see MotionManager for an example on how to use this.*/
00035 template<class MC>
00036 class SharedObject : public SharedObjectBase {
00037 public:
00038   //!if you really need more than 5 arguments for your class, well, you're one crazy puppy but if you really want to, just make more like shown... (yay templates!)
00039   //!@name templated contructors - allows you to pass constructor arguments on to the object being created
00040 
00041   //! Creates the class with the default constructor
00042   SharedObject() : SharedObjectBase() {
00043     rcr=createRCRegion();
00044     new (rcr->Base()) MC;
00045   }
00046   //! Creates the class, passing its constructor t1
00047   template<class T1> SharedObject(T1 t1) : SharedObjectBase() {
00048     rcr=createRCRegion();
00049     new (rcr->Base()) MC(t1);
00050   }
00051   //! Creates the class, passing its constructor t1 and t2
00052   template<class T1, class T2> SharedObject(T1 t1, T2 t2) : SharedObjectBase(){
00053     rcr=createRCRegion();
00054     new (rcr->Base()) MC(t1,t2);
00055   }
00056   //! Creates the class, passing its constructor t1, t2, and t3
00057   template<class T1, class T2, class T3> SharedObject(T1 t1, T2 t2, T3 t3) : SharedObjectBase(){
00058     rcr=createRCRegion();
00059     new (rcr->Base()) MC(t1,t2,t3);
00060   }
00061   //! Creates the class, passing its constructor t1, t2, t3 and t4
00062   template<class T1, class T2, class T3, class T4> SharedObject(T1 t1, T2 t2, T3 t3, T4 t4) : SharedObjectBase(){
00063     rcr=createRCRegion();
00064     new (rcr->Base()) MC(t1,t2,t3,t4);
00065   }
00066   //! Creates the class, passing its constructor t1, t2, t3, t4 and t5 - if you need more arguments, just add them
00067   template<class T1, class T2, class T3, class T4, class T5> SharedObject(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5) : SharedObjectBase(){
00068     rcr=createRCRegion();
00069     new (rcr->Base()) MC(t1,t2,t3,t4,t5);
00070   }
00071   //@}
00072 
00073   MC* operator->() const { return dataCasted(); } //!< smart pointer to the underlying class
00074   MC& operator*() const { return *dataCasted(); } //!< smart pointer to the underlying class
00075   MC& operator[](int i) const { return dataCasted()[i]; } //!< smart pointer to the underlying class
00076 protected:
00077   //! creates and returns RCRegion of correct size for current class.  Adds a reference (which is removed in the destructor)
00078   static RCRegion * createRCRegion() {
00079     RCRegion * r = new RCRegion(calcsize());
00080     //std::cout << "createRCRegion(): rcr->NumberOfReference()==" << r->NumberOfReference() << std::endl;
00081     r->AddReference();
00082     //std::cout << "createRCRegion()NOW: rcr->NumberOfReference()==" << r->NumberOfReference() << std::endl;
00083     return r;
00084   }
00085   MC* dataCasted() const { return static_cast<MC*>(data()); } //!< returns a correctly typed pointer to the object's memory
00086 
00087   //!Calculates the size of the memory region to be used, rounding up to the nearest page size
00088   /*! Not sure this is completely necessary, but may be nice.  Of course, this also means even
00089    *  small regions are going to be at least 4K (current page size)  If memory gets tight or we
00090    *  get a lot of little regions floating around, this might be worth checking into */
00091   static unsigned int calcsize() {
00092     size_t size = sizeof(MC);
00093     sError error;
00094     size_t page_size;
00095     error = GetPageSize(&page_size);
00096     if (error != sSUCCESS) {
00097       cout << "error: " << error << " getting page size in SharedMem" << endl;
00098       page_size = 4096;
00099     }
00100     
00101     int new_size,num_pages;
00102     num_pages = (size+page_size-1)/page_size;
00103     new_size = num_pages*page_size;
00104     //cout << "req" << size << "new" << new_size << "ps" << page_size << endl;
00105     /*    cout << "data size is " << sizeof(MC) << endl;
00106           cout << "msg size is " << MotionManagerMsg::SIZEOF_MSG << endl;
00107           cout << "SIZE is " << rcr->Size() << endl;
00108           cout << "PAGE is " << page_size << endl;
00109           cout << "BASE is " << (void*)rcr->Base() << endl; */
00110     return new_size;
00111   }
00112 };
00113 
00114 /*! @file
00115  * @brief Defines SharedObject, a wrapper for objects in order to facilitate sending them between processes
00116  * @author ejt (Creator)
00117  *
00118  * $Author: ejt $
00119  * $Name: tekkotsu-2_2_1 $
00120  * $Revision: 1.3 $
00121  * $State: Rel $
00122  * $Date: 2003/09/12 23:42:12 $
00123  */
00124 
00125 #endif //INCLUDED_SharedObject_h

Tekkotsu v2.2.1
Generated Tue Nov 23 16:36:39 2004 by Doxygen 1.3.9.1