| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef moses_MmapAllocator_h |
| | #define moses_MmapAllocator_h |
| |
|
| | #include <limits> |
| | #include <iostream> |
| | #include <cstdio> |
| |
|
| | #if defined(_WIN32) || defined(_WIN64) |
| | #define _WINSOCKAPI_ |
| | #include <windows.h> |
| | #include <io.h> |
| | #else |
| | #include <sys/mman.h> |
| | #include <unistd.h> |
| | #endif |
| |
|
| | #include "util/mmap.hh" |
| |
|
| | namespace Moses2 |
| | { |
| | template<class T> |
| | class MmapAllocator |
| | { |
| | protected: |
| | std::FILE* m_file_ptr; |
| | size_t m_file_desc; |
| |
|
| | size_t m_page_size; |
| | size_t m_map_size; |
| |
|
| | char* m_data_ptr; |
| | size_t m_data_offset; |
| | bool m_fixed; |
| | size_t* m_count; |
| |
|
| | public: |
| | typedef T value_type; |
| | typedef T* pointer; |
| | typedef const T* const_pointer; |
| | typedef T& reference; |
| | typedef const T& const_reference; |
| | typedef std::size_t size_type; |
| | typedef std::ptrdiff_t difference_type; |
| |
|
| | MmapAllocator() throw () : |
| | m_file_ptr(std::tmpfile()), m_file_desc(fileno(m_file_ptr)), m_page_size( |
| | util::SizePage()), m_map_size(0), m_data_ptr(0), m_data_offset(0), m_fixed( |
| | false), m_count(new size_t(0)) { |
| | } |
| |
|
| | MmapAllocator(std::FILE* f_ptr) throw () : |
| | m_file_ptr(f_ptr), m_file_desc(fileno(m_file_ptr)), m_page_size( |
| | util::SizePage()), m_map_size(0), m_data_ptr(0), m_data_offset(0), m_fixed( |
| | false), m_count(new size_t(0)) { |
| | } |
| |
|
| | MmapAllocator(std::FILE* f_ptr, size_t data_offset) throw () : |
| | m_file_ptr(f_ptr), m_file_desc(fileno(m_file_ptr)), m_page_size( |
| | util::SizePage()), m_map_size(0), m_data_ptr(0), m_data_offset( |
| | data_offset), m_fixed(true), m_count(new size_t(0)) { |
| | } |
| |
|
| | MmapAllocator(std::string fileName) throw () : |
| | m_file_ptr(std::fopen(fileName.c_str(), "wb+")), m_file_desc( |
| | fileno(m_file_ptr)), m_page_size(util::SizePage()), m_map_size(0), m_data_ptr( |
| | 0), m_data_offset(0), m_fixed(false), m_count(new size_t(0)) { |
| | } |
| |
|
| | MmapAllocator(const MmapAllocator& c) throw () : |
| | m_file_ptr(c.m_file_ptr), m_file_desc(c.m_file_desc), m_page_size( |
| | c.m_page_size), m_map_size(c.m_map_size), m_data_ptr(c.m_data_ptr), m_data_offset( |
| | c.m_data_offset), m_fixed(c.m_fixed), m_count(c.m_count) { |
| | (*m_count)++; |
| | } |
| |
|
| | ~MmapAllocator() throw () { |
| | if (m_data_ptr && *m_count == 0) { |
| | util::UnmapOrThrow(m_data_ptr, m_map_size); |
| | if (!m_fixed && std::ftell(m_file_ptr) != -1) std::fclose(m_file_ptr); |
| | } |
| | (*m_count)--; |
| | } |
| |
|
| | template<class U> |
| | struct rebind { |
| | typedef MmapAllocator<U> other; |
| | }; |
| |
|
| | pointer address(reference value) const { |
| | return &value; |
| | } |
| |
|
| | const_pointer address(const_reference value) const { |
| | return &value; |
| | } |
| |
|
| | size_type max_size() const throw () { |
| | return std::numeric_limits<size_t>::max() / sizeof(value_type); |
| | } |
| |
|
| | pointer allocate(size_type num, const void* = 0) { |
| | m_map_size = num * sizeof(T); |
| |
|
| | #if defined(_WIN32) || defined(_WIN64) |
| | |
| | const int map_shared = 0; |
| | #else |
| | const int map_shared = MAP_SHARED; |
| | #endif |
| | if (!m_fixed) { |
| | size_t read = 0; |
| | #ifdef _WIN32 |
| | read += _chsize_s(m_file_desc, m_map_size); |
| | #else |
| | read += ftruncate(m_file_desc, m_map_size); |
| | #endif |
| | m_data_ptr = (char *) util::MapOrThrow(m_map_size, true, map_shared, |
| | false, m_file_desc, 0); |
| | return (pointer) m_data_ptr; |
| | } else { |
| | const size_t map_offset = (m_data_offset / m_page_size) * m_page_size; |
| | const size_t relative_offset = m_data_offset - map_offset; |
| | const size_t adjusted_map_size = m_map_size + relative_offset; |
| |
|
| | m_data_ptr = (char *) util::MapOrThrow(adjusted_map_size, false, |
| | map_shared, false, m_file_desc, map_offset); |
| |
|
| | return (pointer) (m_data_ptr + relative_offset); |
| | } |
| | } |
| |
|
| | void deallocate(pointer p, size_type num) { |
| | if (!m_fixed) { |
| | util::UnmapOrThrow(p, num * sizeof(T)); |
| | } else { |
| | const size_t map_offset = (m_data_offset / m_page_size) * m_page_size; |
| | const size_t relative_offset = m_data_offset - map_offset; |
| | const size_t adjusted_map_size = m_map_size + relative_offset; |
| |
|
| | util::UnmapOrThrow((pointer) ((char*) p - relative_offset), |
| | adjusted_map_size); |
| | } |
| | } |
| |
|
| | void construct(pointer p, const T& value) { |
| | if (!m_fixed) new (p) value_type(value); |
| | } |
| | void destroy(pointer p) { |
| | if (!m_fixed) p->~T(); |
| | } |
| |
|
| | template<class T1, class T2> |
| | friend bool operator==(const MmapAllocator<T1>&, |
| | const MmapAllocator<T2>&) throw (); |
| |
|
| | template<class T1, class T2> |
| | friend bool operator!=(const MmapAllocator<T1>&, |
| | const MmapAllocator<T2>&) throw (); |
| | }; |
| |
|
| | template<class T1, class T2> |
| | bool operator==(const MmapAllocator<T1>& a1, |
| | const MmapAllocator<T2>& a2) throw () |
| | { |
| | bool equal = true; |
| | equal &= a1.m_file_ptr == a2.m_file_ptr; |
| | equal &= a1.m_file_desc == a2.m_file_desc; |
| | equal &= a1.m_page_size == a2.m_page_size; |
| | equal &= a1.m_map_size == a2.m_map_size; |
| | equal &= a1.m_data_ptr == a2.m_data_ptr; |
| | equal &= a1.m_data_offset == a2.m_data_offset; |
| | equal &= a1.m_fixed == a2.m_fixed; |
| | return equal; |
| | } |
| |
|
| | template<class T1, class T2> |
| | bool operator!=(const MmapAllocator<T1>& a1, |
| | const MmapAllocator<T2>& a2) throw () |
| | { |
| | return !(a1 == a2); |
| | } |
| |
|
| | } |
| |
|
| | #endif |
| |
|