LCOV - code coverage report
Current view: top level - lunchbox - memoryMap.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 63 78 80.8 %
Date: 2016-11-11 05:21:33 Functions: 17 19 89.5 %

          Line data    Source code
       1             : 
       2             : /* Copyright (c) 2009-2016, 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             : #include <stdexcept>
      31             : 
      32             : namespace lunchbox
      33             : {
      34             : namespace detail
      35             : {
      36             : class MemoryMap
      37             : {
      38             : public:
      39           3 :     MemoryMap() : ptr( nullptr ) , size( 0 ), map_( 0 ) {}
      40             : 
      41           8 :     void* init( const std::string& filename, const size_t size_ )
      42             :     {
      43           8 :         if( ptr )
      44             :         {
      45           1 :             LBWARN << "File already mapped" << std::endl;
      46           1 :             return nullptr;
      47             :         }
      48             : 
      49           7 :         init_( filename, size_ );
      50           7 :         return ptr;
      51             :     }
      52             : 
      53           4 :     void unmap()
      54             :     {
      55           4 :         if( !ptr )
      56           0 :             return;
      57             : 
      58           4 :         unmap_();
      59           4 :         ptr = nullptr;
      60           4 :         size = 0;
      61             :     }
      62             : 
      63             :     void* ptr;
      64             :     size_t size;
      65             : 
      66             : private:
      67             : #ifdef _WIN32
      68             :     void* map_;
      69             : 
      70             :     void init_( const std::string& filename, const size_t size_ )
      71             :     {
      72             :         // try to open binary file (and size it)
      73             :         const DWORD access = size_ ? GENERIC_READ | GENERIC_WRITE:GENERIC_READ;
      74             :         const DWORD create = size_ ? CREATE_ALWAYS : OPEN_EXISTING;
      75             :         HANDLE file = ::CreateFile( filename.c_str(), access, FILE_SHARE_READ,
      76             :                                     0, create, FILE_ATTRIBUTE_NORMAL, 0 );
      77             :         if( file == INVALID_HANDLE_VALUE )
      78             :         {
      79             :             LBWARN << "Can't open " << filename << ": " << sysError <<std::endl;
      80             :             return;
      81             :         }
      82             : 
      83             :         if( size_ )
      84             :         {
      85             :             ::SetFilePointer( file, LONG(size_), PLONG(&size_)+1, FILE_BEGIN );
      86             :             ::SetEndOfFile( file );
      87             :         }
      88             : 
      89             :         // create a file mapping
      90             :         const DWORD mode = size_ ? PAGE_READWRITE : PAGE_READONLY;
      91             :         map_ = ::CreateFileMapping( file, 0, mode, 0, 0, 0 );
      92             :         if( !map_ )
      93             :         {
      94             :             ::CloseHandle( file );
      95             :             LBWARN << "File mapping failed: " << sysError << std::endl;
      96             :             return;
      97             :         }
      98             : 
      99             :         // get a view of the mapping
     100             :         ptr = ::MapViewOfFile( map_, size_ ? FILE_MAP_WRITE :
     101             :                                              FILE_MAP_READ, 0, 0, 0 );
     102             : 
     103             :         // get size
     104             :         DWORD highSize;
     105             :         const DWORD lowSize = ::GetFileSize( file, &highSize );
     106             :         size = lowSize | ( static_cast< uint64_t >( highSize ) << 32 );
     107             :         LBASSERT( size_ == 0 || size_ == size );
     108             : 
     109             :         ::CloseHandle( file );
     110             :     }
     111             : 
     112             :     void unmap_()
     113             :     {
     114             :         ::UnmapViewOfFile( ptr );
     115             :         ::CloseHandle( map_ );
     116             :         map_ = 0;
     117             :     }
     118             : 
     119             : #else
     120             : 
     121             :     int map_;
     122             : 
     123           7 :     void init_( const std::string& filename, const size_t size_ )
     124             :     {
     125             :         // try to open binary file (and size it)
     126           7 :         const int flags = size_ ? O_RDWR | O_CREAT : O_RDONLY;
     127           7 :         map_ = ::open( filename.c_str(), flags, S_IRUSR | S_IWUSR );
     128           7 :         if( map_ < 0 )
     129             :         {
     130           3 :             LBINFO << "Can't open " << filename << ": " << sysError <<std::endl;
     131           6 :             return;
     132             :         }
     133             : 
     134           4 :         if( size_ > 0 && ::ftruncate( map_, size_ ) != 0 )
     135             :         {
     136           0 :             LBINFO << "Can't resize " << filename << ": " << sysError
     137           0 :                    << std::endl;
     138           0 :             return;
     139             :         }
     140             : 
     141             :         // retrieve file information
     142             :         struct stat status;
     143           4 :         ::fstat( map_, &status );
     144             : 
     145             :         // create memory mapped file
     146           4 :         size = status.st_size;
     147           4 :         LBASSERTINFO( size_ == 0 || size_ == size, size << " ? " << size_ );
     148             : 
     149           4 :         const int mapFlags = size_ ? PROT_READ | PROT_WRITE : PROT_READ;
     150           4 :         ptr = ::mmap( 0, size, mapFlags, MAP_SHARED, map_, 0 );
     151           4 :         if( ptr == MAP_FAILED )
     152             :         {
     153           0 :             ::close( map_ );
     154           0 :             ptr = nullptr;
     155           0 :             size = 0;
     156           0 :             map_ = 0;
     157             :         }
     158             :     }
     159             : 
     160           4 :     void unmap_()
     161             :     {
     162           4 :         ::munmap( ptr, size );
     163           4 :         ::close( map_ );
     164           4 :         map_ = 0;
     165           4 :     }
     166             : #endif
     167             : };
     168             : }
     169             : 
     170           0 : MemoryMap::MemoryMap()
     171           0 :     : impl_( new detail::MemoryMap )
     172             : {
     173           0 : }
     174             : 
     175           1 : MemoryMap::MemoryMap( const std::string& filename )
     176           1 :     : impl_( new detail::MemoryMap )
     177             : {
     178           1 :     if( !map( filename ))
     179           1 :         LBTHROW( std::runtime_error( "Can't map file" ));
     180           0 : }
     181             : 
     182           2 : MemoryMap::MemoryMap( const std::string& filename, const size_t size )
     183           2 :     : impl_( new detail::MemoryMap )
     184             : {
     185           2 :     if( !create( filename, size ))
     186           1 :         LBTHROW( std::runtime_error( "Can't create file" ));
     187           1 : }
     188             : 
     189           2 : MemoryMap::~MemoryMap()
     190             : {
     191           1 :     unmap();
     192           1 :     delete impl_;
     193           1 : }
     194             : 
     195           4 : const void* MemoryMap::map( const std::string& filename )
     196             : {
     197           4 :     return impl_->init( filename, 0 );
     198             : }
     199             : 
     200           1 : const void* MemoryMap::remap( const std::string& filename )
     201             : {
     202           1 :     unmap();
     203           1 :     return impl_->init( filename, 0 );
     204             : }
     205             : 
     206           3 : void* MemoryMap::create( const std::string& filename, const size_t size )
     207             : {
     208           3 :     LBASSERT( size > 0 );
     209           3 :     if( size == 0 )
     210           0 :         return nullptr;
     211             : 
     212           3 :     return impl_->init( filename, size );
     213             : }
     214             : 
     215           1 : void* MemoryMap::recreate( const std::string& filename, const size_t size )
     216             : {
     217           1 :     unmap();
     218           1 :     return create( filename, size );
     219             : }
     220             : 
     221           4 : void MemoryMap::unmap()
     222             : {
     223           4 :     impl_->unmap();
     224           4 : }
     225             : 
     226           0 : const void* MemoryMap::getAddress() const
     227             : {
     228           0 :     return impl_->ptr;
     229             : }
     230             : 
     231           2 : void* MemoryMap::getAddress()
     232             : {
     233           2 :     return impl_->ptr;
     234             : }
     235             : 
     236           3 : size_t MemoryMap::getSize() const
     237             : {
     238           3 :     return impl_->size;
     239             : }
     240             : 
     241          72 : }

Generated by: LCOV version 1.11