src/MemoryMap.cpp
changeset 0 31a43d94cc26
child 2 851de24ecb61
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/MemoryMap.cpp	Sun Sep 20 15:14:12 2009 -0700
     1.3 @@ -0,0 +1,103 @@
     1.4 +/*
     1.5 + *  MemoryMap.cpp
     1.6 + *  Ottoman
     1.7 + *
     1.8 + *  Created by Jens Alfke on 9/17/09.
     1.9 + *  Copyright 2009 Jens Alfke. All rights reserved.
    1.10 + *  BSD-Licensed: See the file "LICENSE.txt" for details.
    1.11 + */
    1.12 +
    1.13 +#include "MemoryMap.h"
    1.14 +
    1.15 +#include <errno.h>
    1.16 +#include <stdio.h>
    1.17 +#include <sys/mman.h>
    1.18 +
    1.19 +namespace Mooseyard {
    1.20 +
    1.21 +    MemoryMap::~MemoryMap() {
    1.22 +        for (int i=0; i<_nRegions; i++)
    1.23 +            delete _regions[i];
    1.24 +        free(_regions);
    1.25 +    }
    1.26 +
    1.27 +    void MemoryMap::mapRegion (off_t pos, size_t length) {
    1.28 +        size_t end = pos+length;
    1.29 +        for (int i=0; i<_nRegions; i++) {
    1.30 +            Region *region = _regions[i];
    1.31 +            if (region->position() <= pos) {
    1.32 +                if (end <= region->end())
    1.33 +                    return;     // found an existing region covering this range
    1.34 +                else if (region->setLength(end - region->position()))
    1.35 +                    return;     // able to grow the existing region
    1.36 +            }
    1.37 +        }
    1.38 +        
    1.39 +        // No existing region, so add a new one:
    1.40 +        Region *region = new Region(_file, pos,length);
    1.41 +        _regions = (Region**) realloc(_regions, (_nRegions+1)*sizeof(*_regions));
    1.42 +        _regions[_nRegions++] = region;
    1.43 +    }
    1.44 +
    1.45 +    const void* MemoryMap::_at (off_t pos) const {
    1.46 +        for (int i=0; i<_nRegions; i++) {
    1.47 +            const void *ptr = _regions[i]->mappedPosition(pos);
    1.48 +            if (ptr)
    1.49 +                return ptr;
    1.50 +        }
    1.51 +        return NULL;
    1.52 +    }
    1.53 +    
    1.54 +    const void* MemoryMap::mappedPosition (off_t pos) const {
    1.55 +        const void *result = _at(pos);
    1.56 +        if (!result)
    1.57 +            throw File::Error("No memory mapped at this position");
    1.58 +        return result;
    1.59 +    }
    1.60 +
    1.61 +    
    1.62 +    
    1.63 +    
    1.64 +    MemoryMap::Region::Region (File* file, off_t position, size_t length)
    1.65 +    :_file(file),
    1.66 +    _position(position),
    1.67 +    _length (length),
    1.68 +    _start( (const uint8_t*) ::mmap(NULL, length, PROT_READ, MAP_PRIVATE, file->_fd, position) )
    1.69 +    {
    1.70 +        printf("File#%i: Mapped (%6llu -- %6llu) --> %p\n", file->_fd, _position, end(), _start);
    1.71 +        if (_start==NULL || _start == MAP_FAILED) {
    1.72 +            _start = NULL;
    1.73 +            throw File::Error(errno, strerror(errno));
    1.74 +        }
    1.75 +    }
    1.76 +    
    1.77 +    MemoryMap::Region::~Region() {
    1.78 +        if (_start) {
    1.79 +            printf("File#%i: Unmapped (%6llu -- %6llu) from %p\n", _file->_fd, _position, end(), _start);
    1.80 +            ::munmap((void*)_start,_length);
    1.81 +        }
    1.82 +    }
    1.83 +    
    1.84 +    bool MemoryMap::Region::setLength (size_t length) {
    1.85 +        if (length != _length) {
    1.86 +            printf("File#%i: Resiging (%6llu -- %6llu) from %lu to %lu ...", 
    1.87 +                   _file->_fd, _position, end(), _length,length);
    1.88 +            if (::mmap((void*)_start, length, PROT_READ, MAP_PRIVATE | MAP_FIXED, _file->_fd, _position) == MAP_FAILED) {
    1.89 +                printf("failed! errno=%i\n", errno);
    1.90 +                return false;
    1.91 +            }
    1.92 +            printf("OK\n");
    1.93 +            _length = length;
    1.94 +        }
    1.95 +        return true;
    1.96 +    }
    1.97 +    
    1.98 +    const void* MemoryMap::Region::mappedPosition (off_t pos) {
    1.99 +        if (pos >= _position && pos < end())
   1.100 +            return _start + (pos-_position);
   1.101 +        else
   1.102 +            return NULL;
   1.103 +    }
   1.104 +    
   1.105 +    
   1.106 +}