#ifndef __GEOWORLDPAGING_H__ #define __GEOWORLDPAGING_H__ #include #include #include #include #include #include #include #include "gwtypes.h" #include "gwutil.h" #include "geoworld.h" #include "stratum.h" namespace geoworld { typedef mars::OctTree_SphereIndexed< MineralPtr, GeoSpherePack::SCALAR > OctTreeMineralDeposits; class GeoWorldPage { private: GeoHeightMap _heightmap; Stratum _stratum; OctTreeMineralDeposits _minerals; mutable bool _bShouldAbort; mutable size_t _nIFaceRefCount; GW_MUTEX(atomic); GW_MUTEX(work); void checkOutIFace () const; void checkInIFace () const; public: class IFaceEx : public std::exception { public: const std::string message; IFaceEx (const char * szMsg) : message(szMsg) {} }; class Interface { private: GeoWorldPage * _pParent; GW_MUTEX(atomic); public: GeoHeightMap & heightmap; Stratum & stratum; OctTreeMineralDeposits & minerals; Interface (GeoWorldPage * pParent); Interface (Interface && move); ~Interface(); Stratum::View * createStratumView (const WorldUnit nLeft, const WorldUnit nTop, const int nShallow, const WorldUnit nRight, const WorldUnit nBottom, const WorldUnit nDeep) const; Stratum::View * createStratumView (const WorldUnit nLeft, const WorldUnit nTop, const WorldUnit nRight, const WorldUnit nBottom) const; void releaseStratumView (const Stratum::View * pView) const; GeoHeightMap::View * createHeightMapView (const unsigned short nLeft, const unsigned short nTop, const unsigned short nRight, const unsigned short nBottom) const; void releaseHeightMapView (const GeoHeightMap::View * pView) const; inline bool isAborted() const { return _pParent->isAborted(); } }; const unsigned int x, y; GeoWorldPage(const GeoHeightMap::View & hm, const unsigned int nPageX, const unsigned int nPageY, const unsigned short nDepth, const size_t nLayers); ~GeoWorldPage(); void abort (const bool bWait = false) const; bool isAborted() const; const Interface acquireInterface() const { return Interface(const_cast< GeoWorldPage * > (this)); } Interface acquireInterface() { return Interface(this); } }; class InstanceFile { public: class Ex : public std::exception { public: const std::string message; Ex (const char * szMsg) : message(szMsg) {} }; struct InfoHeader { char IDENT[4]; unsigned long endian; unsigned short version; unsigned short stratumcount; unsigned short dim, depth; InfoHeader(); bool validate() const; }; InstanceFile(); InstanceFile(const unsigned short nDim, const unsigned short nDepth, const unsigned short nLayerCount); ~InstanceFile(); inline const Stratum & getStratum() const { return *_pStratum; } inline Stratum & getStratum() { return *_pStratum; } inline GeoHeightMap::View & top () { return _pStratum->getBase(); } inline const GeoHeightMap::View & top () const { return _pStratum->getBase(); } inline GeoStratumField::View & layer (const size_t c) { return _pStratum->field(c); } inline const GeoStratumField::View & layer (const size_t c) const { return _pStratum->field(c); } static void write (const std::string & sFileName, const InstanceFile * pInstFile); static InstanceFile * load (const std::string & sFileName); private: Stratum * _pStratum; unsigned short _nDim, _nDepth; static std::fstream * open (const std::string & sFileName, const std::ios::openmode & nMode); std::ostream & operator >> (std::ostream & outs) const; std::istream & operator << (std::istream & ins); }; class PagingStore { public: PagingStore (const std::string & sFileName, const std::string & sStoreDirectory, const std::string & sFilePrefix = "gwpage-", const std::string & sFileSuffix = ".gwp"); GeoWorldPage * requestPage (const unsigned int nPageX, const unsigned int nPageY); void releasePage (GeoWorldPage * pPage); std::string makeFilename (const unsigned int nPageX, const unsigned int nPageY) const; static unsigned long calculatePageID (const unsigned int nPageX, const unsigned int nPageY); inline unsigned int getNumPagesWide () const { return _pFile->getTilesWide(); } inline unsigned int getNumPagesHigh () const { return _pFile->getTilesHigh(); } ~PagingStore(); private: FileSource * _pFile; std::string _sFilePrefix, _sFileSuffix, _sStoreDirectory; FileSource::MainDEM::Block * _pUtilityBlock; InstanceFile * loadInstanceFile( const unsigned int nPageX, const unsigned int nPageY ) const; void logBorders( const GeoHeightMap::View &base, const unsigned int nPageX, const unsigned int nPageY ); GW_MUTEX(mtxMaster); class PageMutexProvider { public: class NeighborhoodMutex { public: enum Spot { N = 0, W = 1, E = 2, S = 3, C = 4, TotalSpots = 5 }; explicit NeighborhoodMutex (boost::shared_mutex * const * ppmtx); NeighborhoodMutex(NeighborhoodMutex && movable); ~NeighborhoodMutex(); void genLock(); private: NeighborhoodMutex (const NeighborhoodMutex & copy); NeighborhoodMutex & operator = (const NeighborhoodMutex & copy); typedef boost::upgrade_lock< boost::shared_mutex > preamble_lock; typedef boost::upgrade_to_unique_lock< boost::shared_mutex > upgraded_lock; typedef boost::unique_lock< boost::shared_mutex > gen_lock; typedef boost::shared_lock< boost::shared_mutex > qry_lock; typedef DetachableScopedTryLock< boost::shared_mutex, qry_lock > DetachableScopedQueryTryLock; typedef DetachableScopedTryLock< boost::shared_mutex, gen_lock > DetachableScopedGenerationTryLock; boost::shared_mutex * _pmtxNeighbors[TotalSpots]; qry_lock * _plckNeighbors[TotalSpots]; gen_lock * _plckCenter; preamble_lock * _plckPreamble; STATIC_GW_MUTEX(ATOMIC); }; PageMutexProvider (const unsigned int nCellsX, const unsigned int nCellsY); ~PageMutexProvider(); NeighborhoodMutex acquireNeighborhood (const long nPageX, const long nPageY); private: boost::shared_mutex ** _ppShMutexes; unsigned int _nW, _nH; size_t _szLen; size_t idx(const long nPageX, const long nPageY) const; } * _pMutexProvider; }; } #endif