Отображенный в память файл std::allocator при замораживании устройства WM6

У меня есть проект Visual Studio 2008 C++ для Windows Mobile 6.x, где мне нужно больше памяти, чем доступно для меня в слоте для процесса 32 МБ. Итак, я смотрю на использование файлов с отображенной памятью. Я создал стандартную реализацию распределителя, которая заменяет new / delete на CreateFileMapping и MapViewOfFile.

Предполагаемое использование примерно так:

struct Foo
{
    char a[ 1024 ];
};

int _tmain( int argc, _TCHAR* argv[] )
{
    std::vector< boost::shared_ptr< Foo > > v;
    for( int i = 0; i < 40000; ++i )
    {
        v.push_back( boost::allocate_shared< Foo >( MappedFileAllocator< Foo >() ) );
    }
    return 0;
}

С std::allocator, Я могу получить 28197 итераций в этом примере, прежде чем я получу std::bad_alloc исключение. С MappedFileAllocatorЯ получаю 32371 итераций до того, как устройство полностью зависнет и должно быть перезагружено. Поскольку мое устройство имеет 512 МБ оперативной памяти, я ожидал, что смогу получить гораздо больше итераций из этого цикла.

мой MappedFileAllocator реализация это:

template< class T >
class MappedFileAllocator
{
public:
    typedef T         value_type;
    typedef size_t    size_type;
    typedef ptrdiff_t difference_type;
    typedef T*        pointer;
    typedef const T*  const_pointer;
    typedef T&        reference;
    typedef const T&  const_reference;

    pointer address( reference r ) const { return &r; };
    const_pointer address( const_reference r ) const { return &r; };

    /// convert a MappedFileAllocator<T> to a MappedFileAllocator<U>
    template< class U >
    struct rebind { typedef MappedFileAllocator< U > other; };

    MappedFileAllocator() throw() : mapped_file_( INVALID_HANDLE_VALUE ) { };

    template< class U >
    explicit MappedFileAllocator( const MappedFileAllocator< U >& other ) throw()
        : mapped_file_( INVALID_HANDLE_VALUE )
    {
        if( other.mapped_file_ != this->mapped_file_ )
        {
            ::DuplicateHandle( GetCurrentProcess(), 
                other.mapped_file_,
                GetCurrentProcess(),
                &this->mapped_file_,
                0,
                FALSE,
                DUPLICATE_SAME_ACCESS );
        }
    };

    pointer allocate( size_type n, const void* /*hint*/ = 0 )
    {
        if( n > max_size() )
           throw std::bad_alloc();

        if( n > 0 )
        {
            size_type buf_size = n * sizeof( value_type );
            mapped_file_ = ::CreateFileMapping( INVALID_HANDLE_VALUE, 
                NULL,
                PAGE_READWRITE,
                0,
                buf_size,
                L"{45E4FA7B-7B1E-4939-8CBB-811276B5D4DE}" );

            if( NULL == mapped_file_ )
                throw std::bad_alloc();

            LPVOID f = ::MapViewOfFile( mapped_file_, 
                FILE_MAP_READ | FILE_MAP_WRITE, 
                0, 
                0, 
                buf_size );

            if( NULL == f )
            {
                ::CloseHandle( mapped_file_ );
                mapped_file_ = INVALID_HANDLE_VALUE;
                throw std::bad_alloc();
            }
            return reinterpret_cast< T* >( f );
        }

        return 0;
    };

    void deallocate( pointer p, size_type n )
    {
        if( NULL != p )
        {
            ::FlushViewOfFile( p, n * sizeof( T ) );
            ::UnmapViewOfFile( p );
        }
        if( INVALID_HANDLE_VALUE != mapped_file_ )
        {
            ::CloseHandle( mapped_file_ );
            mapped_file_ = INVALID_HANDLE_VALUE;
        }
    };

    size_type max_size() const throw() 
    { 
        return std::numeric_limits< size_type >::max() / sizeof( T );
    };

    /// handle to the memory-mapped file
    HANDLE mapped_file_;

private:

    /// disallow assignment
    void operator=( const MappedFileAllocator& );

}; // class MappedFileAllocator

Кто-нибудь может подсказать, где я могу пойти не так с моим MappedFileAllocator реализация?

Спасибо, Пол

3 ответа

Решение

Я только что получил значок "популярный вопрос" для этого, поэтому я решил (запоздало) опубликовать ответ. У меня кончились доступные ручки. В ядре Windows Mobile имеется неподписанный короткий счетчик, связанный с переполнением выделения дескриптора. Как только это произошло, устройство зависнет.

Проверьте, поддерживает ли boost:: interprocess Windows Mobile. У них есть средства для создания отображенных в память файлов и использования памяти для выделения любого фрагмента данных, который вы хотите:

http://www.boost.org/doc/libs/1_47_0/doc/html/interprocess/sharedmemorybetweenprocesses.html

Вы используете анонимное сопоставление файлов (без реального файла, поддерживающего его). Когда вы делаете это, отображение поддерживается файлом системной страницы. Вполне вероятно, что мобильная ОС на самом деле не имеет файла подкачки, потому что "жесткий диск", вероятно, является флэш-устройством. Как правило, делать разбиение на страницы виртуальной памяти на флэш-устройствах - плохая идея, поскольку природа виртуальной памяти означает большой объем операций записи, которые могут быстро сжечь флэш (особенно старые типы).

Это подтверждается количеством итераций, которые вы получаете. Похоже, вы можете отобразить примерно до 60% от общей памяти на вашем устройстве.

Вы, вероятно, можете заставить это работать с большими разделами, если вы откроете реальный файл (используя OpenFile) и сопоставьте это, а не используя INVALID_FILE_HANDLE в CreateFileMapping, Но будьте осторожны с вашим флеш-хранилищем (и производительностью!), Если вы собираетесь много писать в файл-маппинг.

Другие вопросы по тегам