LCOV - code coverage report
Current view: top level - lunchbox - memoryMap.cpp (source / functions) Hit Total Coverage
Test: Lunchbox Lines: 59 76 77.6 %
Date: 2016-03-29 17:09:06 Functions: 16 19 84.2 %

          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           1 :     MemoryMap() : ptr( 0 ) , size( 0 ), map_( 0 ) {}
      39             : 
      40           6 :     void* init( const std::string& filename, const size_t size_ )
      41             :     {
      42           6 :         if( ptr )
      43             :         {
      44           1 :             LBWARN << "File already mapped" << std::endl;
      45           1 :             return 0;
      46             :         }
      47             : 
      48           5 :         init_( filename, size_ );
      49           5 :         return ptr;
      50             :     }
      51             : 
      52           4 :     void unmap()
      53             :     {
      54           4 :         if( !ptr )
      55           4 :             return;
      56             : 
      57           4 :         unmap_();
      58           4 :         ptr = 0;
      59           4 :         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             :             ::CloseHandle( file );
      94             :             LBWARN << "File mapping failed: " << sysError << std::endl;
      95             :             return;
      96             :         }
      97             : 
      98             :         // get a view of the mapping
      99             :         ptr = ::MapViewOfFile( map_, size_ ? FILE_MAP_WRITE :
     100             :                                              FILE_MAP_READ, 0, 0, 0 );
     101             : 
     102             :         // get size
     103             :         DWORD highSize;
     104             :         const DWORD lowSize = ::GetFileSize( file, &highSize );
     105             :         size = lowSize | ( static_cast< uint64_t >( highSize ) << 32 );
     106             :         LBASSERT( size_ == 0 || size_ == size );
     107             : 
     108             :         ::CloseHandle( file );
     109             :     }
     110             : 
     111             :     void unmap_()
     112             :     {
     113             :         ::UnmapViewOfFile( ptr );
     114             :         ::CloseHandle( map_ );
     115             :         map_ = 0;
     116             :     }
     117             : 
     118             : #else
     119             : 
     120             :     int map_;
     121             : 
     122           5 :     void init_( const std::string& filename, const size_t size_ )
     123             :     {
     124             :         // try to open binary file (and size it)
     125           5 :         const int flags = size_ ? O_RDWR | O_CREAT : O_RDONLY;
     126           5 :         map_ = ::open( filename.c_str(), flags, S_IRUSR | S_IWUSR );
     127           5 :         if( map_ < 0 )
     128             :         {
     129           1 :             LBINFO << "Can't open " << filename << ": " << sysError <<std::endl;
     130           2 :             return;
     131             :         }
     132             : 
     133           4 :         if( size_ > 0 && ::ftruncate( map_, size_ ) != 0 )
     134             :         {
     135           0 :             LBINFO << "Can't resize " << filename << ": " << sysError
     136           0 :                    << std::endl;
     137           0 :             return;
     138             :         }
     139             : 
     140             :         // retrieve file information
     141             :         struct stat status;
     142           4 :         ::fstat( map_, &status );
     143             : 
     144             :         // create memory mapped file
     145           4 :         size = status.st_size;
     146           4 :         LBASSERTINFO( size_ == 0 || size_ == size, size << " ? " << size_ );
     147             : 
     148           4 :         const int mapFlags = size_ ? PROT_READ | PROT_WRITE : PROT_READ;
     149           4 :         ptr = ::mmap( 0, size, mapFlags, MAP_SHARED, map_, 0 );
     150           4 :         if( ptr == MAP_FAILED )
     151             :         {
     152           0 :             ::close( map_ );
     153           0 :             ptr = 0;
     154           0 :             size = 0;
     155           0 :             map_ = 0;
     156             :         }
     157             :     }
     158             : 
     159           4 :     void unmap_()
     160             :     {
     161           4 :         ::munmap( ptr, size );
     162           4 :         ::close( map_ );
     163           4 :         map_ = 0;
     164           4 :     }
     165             : #endif
     166             : };
     167             : }
     168             : 
     169           0 : MemoryMap::MemoryMap()
     170           0 :     : impl_( new detail::MemoryMap )
     171             : {
     172           0 : }
     173             : 
     174           0 : MemoryMap::MemoryMap( const std::string& filename )
     175           0 :     : impl_( new detail::MemoryMap )
     176             : {
     177           0 :     map( filename );
     178           0 : }
     179             : 
     180           1 : MemoryMap::MemoryMap( const std::string& filename, const size_t size )
     181           1 :     : impl_( new detail::MemoryMap )
     182             : {
     183           1 :     create( filename, size );
     184           1 : }
     185             : 
     186           1 : MemoryMap::~MemoryMap()
     187             : {
     188           1 :     unmap();
     189           1 :     delete impl_;
     190           1 : }
     191             : 
     192           3 : const void* MemoryMap::map( const std::string& filename )
     193             : {
     194           3 :     return impl_->init( filename, 0 );
     195             : }
     196             : 
     197           1 : const void* MemoryMap::remap( const std::string& filename )
     198             : {
     199           1 :     unmap();
     200           1 :     return impl_->init( filename, 0 );
     201             : }
     202             : 
     203           2 : void* MemoryMap::create( const std::string& filename, const size_t size )
     204             : {
     205           2 :     LBASSERT( size > 0 );
     206           2 :     if( size == 0 )
     207           0 :         return 0;
     208             : 
     209           2 :     return impl_->init( filename, size );
     210             : }
     211             : 
     212           1 : void* MemoryMap::recreate( const std::string& filename, const size_t size )
     213             : {
     214           1 :     unmap();
     215           1 :     return create( filename, size );
     216             : }
     217             : 
     218           4 : void MemoryMap::unmap()
     219             : {
     220           4 :     impl_->unmap();
     221           4 : }
     222             : 
     223           0 : const void* MemoryMap::getAddress() const
     224             : {
     225           0 :     return impl_->ptr;
     226             : }
     227             : 
     228           2 : void* MemoryMap::getAddress()
     229             : {
     230           2 :     return impl_->ptr;
     231             : }
     232             : 
     233           3 : size_t MemoryMap::getSize() const
     234             : {
     235           3 :     return impl_->size;
     236             : }
     237             : 
     238          81 : }

Generated by: LCOV version 1.11