1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
     100
     101
     102
     103
     104
     105
     106
     107
     108
     109
     110
     111
     112
     113
     114
     115
     116
     117
     118
     119
     120
     121
     122
     123
     124
     125
     126
     127
     128
     129
     130
     131
#ifndef MEM_OBJECT_HPP
#define MEM_OBJECT_HPP

#include <exception>
#include <sstream>
#include <sys/mman.h>
#include <unistd.h>

class MemObject
{
    public:
        class Exception: public std::exception {};

        class InvalidMemObject
            : public Exception
        {
            public:
                virtual const char* what() const noexcept
                {
                    return "invalid MemObject";
                }
        };

        class AccessViolation
            : public Exception
        {
            public:
                AccessViolation(off_t off, size_t size, size_t len)
                {
                    std::ostringstream os;
                    os << "access violation: [" << off << ", " << off+size <<
                          ") does not fit into [0, " << len << ")";
                    message = os.str();
                }

                virtual const char* what() const noexcept
                {
                    return message.c_str();
                }

            private:
                std::string message;
        };

        friend void
        swap(MemObject& lhs, MemObject& rhs) noexcept
        {
            using std::swap;
            swap(lhs.fd, rhs.fd);
            swap(lhs.addr, rhs.addr);
            swap(lhs.len, rhs.len);
        }

        MemObject() noexcept
            : fd{-1}, addr{MAP_FAILED}, len{0}
        {
        }

        MemObject(MemObject&& other) noexcept
            : MemObject()
        {
            swap(*this, other);
        }

        MemObject(int fd, off_t off, size_t len, int prot, int flags) noexcept
            : fd{fd}, addr{mmap(nullptr, len, prot, flags, fd, off)}, len{len}
        {
            std::cout << "addr = " << addr << std::endl;
        }

        ~MemObject() noexcept
        {
            if (addr != MAP_FAILED) {
                munmap(addr, len);
            }
            if (fd >= 0) {
                close(fd);
            }
        }

        MemObject&
        operator=(const MemObject&) = delete;

        MemObject&
        operator=(MemObject&& other)
        {
            swap(*this, other);
            return *this;
        }

        bool
        valid() const noexcept
        {
            return addr != MAP_FAILED;
        }

        template<typename T>
        const T&
        access(size_t off) const
            throw(AccessViolation, InvalidMemObject)
        {
            if (!valid()) {
                throw InvalidMemObject();
            }
            if (off0 || off >= len || offsizeof(T) > len) {
                throw AccessViolation(offsizeof(T), len);
            }
            return *(T*)((char*) addr + off);
        }

        template<typename T>
        T&
        access(size_t off)
            throw(AccessViolation, InvalidMemObject)
        {
            if (!valid()) {
                throw InvalidMemObject();
            }
            if (off0 || off >= len || offsizeof(T) > len) {
                throw AccessViolation(offsizeof(T), len);
            }
            return *(T*)((char*) addr + off);
        }

    private:
        int fd;
        void* addr;
        size_t len;
};

#endif