LCOV - code coverage report
Current view: top level - lunchbox - memoryMap.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 54 76 71.1 %
Date: 2014-10-01 Functions: 15 19 78.9 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2013, Stefan Eilemann <eile@equalizergraphics.com>
       3             :  *
       4             :  * This library is free software; you can redistribute it and/or modify it under
       5             :  * the terms of the GNU Lesser General Public License version 2.1 as published
       6             :  * by the Free Software Foundation.
       7             :  *
       8             :  * This library is distributed in the hope that it will be useful, but WITHOUT
       9             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
      10             :  * FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
      11             :  * details.
      12             :  *
      13             :  * You should have received a copy of the GNU Lesser General Public License
      14             :  * along with this library; if not, write to the Free Software Foundation, Inc.,
      15             :  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      16             :  */
      17             : 
      18             : #include "memoryMap.h"
      19             : 
      20             : #include "debug.h"
      21             : #include "os.h"
      22             : #include "types.h"
      23             : 
      24             : #include <fcntl.h>
      25             : #include <sys/stat.h>
      26             : #ifndef _WIN32
      27             : #  include <sys/mman.h>
      28             : #  include <unistd.h>
      29             : #endif
      30             : 
      31             : namespace lunchbox
      32             : {
      33             : namespace detail
      34             : {
      35             : class MemoryMap
      36             : {
      37             : public:
      38         121 :     MemoryMap() : ptr( 0 ) , size( 0 ), map_( 0 ) {}
      39             : 
      40         123 :     void* init( const std::string& filename, const size_t size_ )
      41             :     {
      42         123 :         if( ptr )
      43             :         {
      44           0 :             LBWARN << "File already mapped" << std::endl;
      45           0 :             return 0;
      46             :         }
      47             : 
      48         123 :         init_( filename, size_ );
      49         123 :         return ptr;
      50             :     }
      51             : 
      52         122 :     void unmap()
      53             :     {
      54         122 :         if( !ptr )
      55         122 :             return;
      56             : 
      57         122 :         unmap_();
      58         122 :         ptr = 0;
      59         122 :         size = 0;
      60             :     }
      61             : 
      62             :     void* ptr;
      63             :     size_t size;
      64             : 
      65             : private:
      66             : #ifdef _WIN32
      67             :     void* map_;
      68             : 
      69             :     void init_( const std::string& filename, const size_t size_ )
      70             :     {
      71             :         // try to open binary file (and size it)
      72             :         const DWORD access = size_ ? GENERIC_READ | GENERIC_WRITE:GENERIC_READ;
      73             :         const DWORD create = size_ ? CREATE_ALWAYS : OPEN_EXISTING;
      74             :         HANDLE file = ::CreateFile( filename.c_str(), access, FILE_SHARE_READ,
      75             :                                     0, create, FILE_ATTRIBUTE_NORMAL, 0 );
      76             :         if( file == INVALID_HANDLE_VALUE )
      77             :         {
      78             :             LBWARN << "Can't open " << filename << ": " << sysError <<std::endl;
      79             :             return;
      80             :         }
      81             : 
      82             :         if( size_ )
      83             :         {
      84             :             ::SetFilePointer( file, LONG(size_), PLONG(&size_)+1, FILE_BEGIN );
      85             :             ::SetEndOfFile( file );
      86             :         }
      87             : 
      88             :         // create a file mapping
      89             :         const DWORD mode = size_ ? PAGE_READWRITE : PAGE_READONLY;
      90             :         map_ = ::CreateFileMapping( file, 0, mode, 0, 0, 0 );
      91             :         if( !map_ )
      92             :         {
      93             :             LBWARN << "File mapping failed: " << sysError << std::endl;
      94             :             return;
      95             :         }
      96             : 
      97             :         // get a view of the mapping
      98             :         ptr = ::MapViewOfFile( map_, FILE_MAP_READ, 0, 0, 0 );
      99             : 
     100             :         // get size
     101             :         DWORD highSize;
     102             :         const DWORD lowSize = ::GetFileSize( file, &highSize );
     103             :         size = lowSize | ( static_cast< uint64_t >( highSize ) << 32 );
     104             :         LBASSERT( size_ == 0 || size_ == size );
     105             : 
     106             :         ::CloseHandle( file );
     107             :     }
     108             : 
     109             :     void unmap_()
     110             :     {
     111             :         ::UnmapViewOfFile( ptr );
     112             :         ::CloseHandle( map_ );
     113             :         map_ = 0;
     114             :     }
     115             : 
     116             : #else
     117             : 
     118             :     int map_;
     119             : 
     120         123 :     void init_( const std::string& filename, const size_t size_ )
     121             :     {
     122             :         // try to open binary file (and size it)
     123         123 :         const int flags = size_ ? O_RDWR | O_CREAT : O_RDONLY;
     124         123 :         map_ = ::open( filename.c_str(), flags, S_IRUSR | S_IWUSR );
     125         123 :         if( map_ < 0 )
     126             :         {
     127           1 :             LBINFO << "Can't open " << filename << ": " << sysError <<std::endl;
     128           2 :             return;
     129             :         }
     130             : 
     131         122 :         if( size_ > 0 && ::ftruncate( map_, size_ ) != 0 )
     132             :         {
     133           0 :             LBINFO << "Can't resize " << filename << ": " << sysError
     134           0 :                    << std::endl;
     135           0 :             return;
     136             :         }
     137             : 
     138             :         // retrieve file information
     139             :         struct stat status;
     140         122 :         ::fstat( map_, &status );
     141             : 
     142             :         // create memory mapped file
     143         122 :         size = status.st_size;
     144         122 :         LBASSERTINFO( size_ == 0 || size_ == size, size << " ? " << size_ );
     145             : 
     146         122 :         const int mapFlags = size_ ? PROT_READ | PROT_WRITE : PROT_READ;
     147         122 :         ptr = ::mmap( 0, size, mapFlags, MAP_SHARED, map_, 0 );
     148         122 :         if( ptr == MAP_FAILED )
     149             :         {
     150           0 :             ::close( map_ );
     151           0 :             ptr = 0;
     152           0 :             size = 0;
     153           0 :             map_ = 0;
     154             :         }
     155             :     }
     156             : 
     157         122 :     void unmap_()
     158             :     {
     159         122 :         ::munmap( ptr, size );
     160         122 :         ::close( map_ );
     161         122 :         map_ = 0;
     162         122 :     }
     163             : #endif
     164             : };
     165             : }
     166             : 
     167         120 : MemoryMap::MemoryMap()
     168         120 :     : impl_( new detail::MemoryMap )
     169             : {
     170         120 : }
     171             : 
     172           0 : MemoryMap::MemoryMap( const std::string& filename )
     173           0 :     : impl_( new detail::MemoryMap )
     174             : {
     175           0 :     map( filename );
     176           0 : }
     177             : 
     178           1 : MemoryMap::MemoryMap( const std::string& filename, const size_t size )
     179           1 :     : impl_( new detail::MemoryMap )
     180             : {
     181           1 :     create( filename, size );
     182           1 : }
     183             : 
     184         121 : MemoryMap::~MemoryMap()
     185             : {
     186         121 :     unmap();
     187         121 :     delete impl_;
     188         121 : }
     189             : 
     190         122 : const void* MemoryMap::map( const std::string& filename )
     191             : {
     192         122 :     return impl_->init( filename, 0 );
     193             : }
     194             : 
     195           0 : const void* MemoryMap::remap( const std::string& filename )
     196             : {
     197           0 :     unmap();
     198           0 :     return impl_->init( filename, 0 );
     199             : }
     200             : 
     201           1 : void* MemoryMap::create( const std::string& filename, const size_t size )
     202             : {
     203           1 :     LBASSERT( size > 0 );
     204           1 :     if( size == 0 )
     205           0 :         return 0;
     206             : 
     207           1 :     return impl_->init( filename, size );
     208             : }
     209             : 
     210           0 : void* MemoryMap::recreate( const std::string& filename, const size_t size )
     211             : {
     212           0 :     unmap();
     213           0 :     return create( filename, size );
     214             : }
     215             : 
     216         122 : void MemoryMap::unmap()
     217             : {
     218         122 :     impl_->unmap();
     219         122 : }
     220             : 
     221           0 : const void* MemoryMap::getAddress() const
     222             : {
     223           0 :     return impl_->ptr;
     224             : }
     225             : 
     226           2 : void* MemoryMap::getAddress()
     227             : {
     228           2 :     return impl_->ptr;
     229             : }
     230             : 
     231         123 : size_t MemoryMap::getSize() const
     232             : {
     233         123 :     return impl_->size;
     234             : }
     235             : 
     236          90 : }

Generated by: LCOV version 1.10