From: Andrew J Bromage (ajb_at_[hidden])
Date: 2006-02-08 22:40:59


G'day Ion.

Ion Gaztañaga <igaztanaga <at> gmail.com> writes:

> I hope you can find to do a review, since it seems you have experience
> with memory mappings.

I hope so too. :-)

> If I understand this correctly, you want a class that can map more than
> a fragment of a file holding a single file descriptor, is that right?

Well... I want a way to do that, whether it's a single class or not.

When I first thought about it, the approach that I considered was to use
two classes. mmaped_file represents a file which has zero or more mmaped
regions, and mmaped_region which represents a single region. Off the top
of my head, something like this might be appropriate:

    class mmapped_file : private boost::noncopyable
    {
    public:
        /* A slightly richer set of access modes. If the operating system does
           not support some mode, the library should pick a mode that at least
           allows the required mode. (e.g. if the OS doesn't support write-only
           mode, read-write mode is an appropriate substitute since it allows
           writing. */
        typedef enum {
                  none_mode = 0x00, ro_mode = 0x01, wo_mode = 0x02, rw_mode =
0x03, access_mode_mask = 0xff
        } accessmode;

        /* Open a file, RAII style. Throws an exception on failure. */
        mmapped_file(const char* filename, accessmode mode);

        /* Closes the file. Does not throw. */
        ~mmapped_file();

        /* XXX Support for iterating through the mapped regions? */
    };

    class mmaped_region : private boost::noncopyable
    {
    public:
        /* Map a region from an mmaped_file. Throws an exception on failure. */
        mmaped_region(shared_ptr<mmaped_file>& file, fileoff_t offset,
                      size_t size, mmaped_file::accessmode mode);

        /* Unmap the region. Does not throw. */
        ~mmapped_region();

        /* Get the size of the mapped region. Does not throw. */
        std::size_t get_size() const;

        /* Get a pointer to the base of the mapped region. Does not throw. */
        void* get_base() const;

        /* Get the file offset of the beginning of the mapped region. Does not
throw. */
        fileoff_t get_file_offset() const;

        /* Flush an area of the mapped region. Does not throw. */
        bool flush(size_t mapping_offset = 0, size_t numbytes = 0);
    };

mmaped_region holds a shared_ptr to an mmaped_file, so that when the
last mapped region is destroyed, the file is closed (assuming someone
else isn't holding onto if, of course).

Cheers,
Andrew Bromage