Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

RegionRegistry.h

Go to the documentation of this file.
00001 //-*-c++-*-
00002 #ifndef INCLUDED_RegionRegistry_h_
00003 #define INCLUDED_RegionRegistry_h_
00004 
00005 #ifdef PLATFORM_APERIOS
00006 #  warning RegionRegistry is not Aperios compatable
00007 #else
00008 
00009 #include "ListMemBuf.h"
00010 #include "RCRegion.h"
00011 #include "Shared/MarkScope.h"
00012 #include "ProcessID.h"
00013 
00014 //! Keeps track of currently available shared memory regions
00015 template<unsigned int MAX_REGIONS, unsigned int NAME_LEN>
00016 class RegionRegistry {
00017 protected:
00018   //! makes sure we only have one registration in progress at a time
00019   mutable MutexLock<ProcessID::NumProcesses> lock;
00020   
00021   //! Holds information regarding a shared memory region available for listening
00022   struct entry {
00023     //! constructor, provides an empty name
00024     entry() : id() { name[0]='\0'; }
00025     //! constructor, pass name and pointer to region
00026     entry(const char n[], RCRegion* r) : id(r->ID()) {
00027       strncpy(name,n,NAME_LEN);
00028       name[NAME_LEN]='\0';
00029     }
00030     char name[NAME_LEN+1]; //!< the name for the region
00031     RCRegion::Identifier id; //!< stores information needed to identify the region to the system
00032   };
00033   typedef ListMemBuf<entry,MAX_REGIONS> registry_t;  //!< type of the collection managing the regions
00034   registry_t avail; //!< collection of available memory regions
00035 
00036 public:
00037   static const unsigned int CAPACITY=MAX_REGIONS; //!< allows access to template parameters
00038   static const unsigned int REGION_NAME_LEN=NAME_LEN; //!< allows access to template parameters
00039   typedef typename registry_t::index_t index_t; //!< shorthand for the index type used to reference regions
00040 
00041   //! constructor
00042   RegionRegistry() : lock(), avail() {}
00043   
00044   //! destructor
00045   ~RegionRegistry() {
00046     MarkScope autolock(lock);
00047     avail.clear();
00048   }
00049   
00050   //! Searches for the region specified by @a name, returns end() if not found
00051   index_t findRegion(const std::string& name) const {
00052     MarkScope autolock(lock);
00053     if(name.size()>NAME_LEN)
00054       std::cerr << "WARNING: RegionRegistry::attach("<<name<<") is too long, max is " << NAME_LEN << std::endl;
00055     for(index_t it=begin(); it!=end(); it=next(it))
00056       if(name==avail[it].name)
00057         return it;
00058     return avail.end();
00059   }
00060 
00061   //! Registers a region, returns the index of the region if successful, or end() if out of space or conflicting registration is found.
00062   /*! You can re-register the same region under the same name, it simply returns the same index again. */
00063   index_t registerRegion(const std::string& name, const RCRegion * region) {
00064     MarkScope autolock(lock,ProcessID::getID());
00065     index_t it=findRegion(name);
00066     if(it!=end()) { //found, already registered
00067       if(avail[it].regions[ProcessID::getID()]==region)
00068         return it; //same one, just return it
00069       return end(); // conflict, return invalid
00070     }
00071     //not found, make a new one
00072     return avail.push_back(entry(name.c_str(),region));
00073   }
00074   
00075   //! Creates and registers a new region of the specified size — if the region is already registered, the previous one is returned.
00076   /*! No checking is done on the size of the region... if it was already registered as a different size, that is ignored. */
00077   RCRegion * registerRegion(const std::string& name, size_t size) {
00078     MarkScope autolock(lock);
00079     index_t it=findRegion(name);
00080     if(it!=end()) {
00081       //found, already registered
00082       return RCRegion::attach(avail[it].id);
00083     } else {
00084       //not found:
00085       RCRegion * region = new RCRegion(name,size);
00086       avail.push_back(entry(name.c_str(),region));
00087       return region;
00088     }
00089   }
00090   
00091   //! Access a region by index
00092   RCRegion * operator[](index_t it) const {
00093     MarkScope autolock(lock,ProcessID::getID());
00094     if(it==end())
00095       return NULL;
00096     return RCRegion::attach(avail[it].id);
00097   }
00098   
00099   //! Erases the registration, but doesn't dereference the region (the registry doesn't claim references on the regions...)
00100   void erase(index_t it) {
00101     MarkScope autolock(lock,ProcessID::getID());
00102     avail.erase(it);
00103   }
00104   
00105   index_t begin() const { return avail.begin(); } //!< provides iteration through the entries, be sure to use next(), the index_t is not a 'proper' iterator (no ++ to increment)
00106   index_t next(index_t it) const { return avail.next(it); } //!< provides the index of the next entry
00107   index_t end() const { return avail.end(); } //!< one-past-end marker
00108 };
00109 
00110 /*! @file
00111  * @brief Defines RegionRegistry, which keeps track of currently available shared memory regions
00112  * @author ejt (Creator)
00113  */
00114 
00115 #endif //Aperios check
00116 
00117 #endif //INCLUDED
00118 

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:50 2016 by Doxygen 1.6.3