Reputation: 7863
I have a Visual Studio 2008 C++ project for Windows Mobile 6.x where I need more memory than is available to me in the 32MB process slot. So, I'm looking at using memory mapped files. I've created a standard allocator implementation that replaces new/delete with CreateFileMapping and MapViewOfFile.
The intended use is something like this:
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;
}
With the std::allocator
, I can get 28197 iterations in that example before I get a std::bad_alloc
exception. With the MappedFileAllocator
, I get 32371 iterations before the device completely freezes and has to be rebooted. Since my device has 512MB of RAM, I expected to be able to get far more iterations out of that loop.
My MappedFileAllocator
implementation is:
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
Can anybody suggest where I may be going wrong with my MappedFileAllocator
implementation?
Thanks, PaulH
Upvotes: 9
Views: 1720
Reputation: 7863
I just got the "popular question" badge for this one, so I thought I'd (belatedly) post the answer. I was running out of available handles. There is an unsigned short counter in the Windows Mobile kernel relating to handle allocation that was overflowing. Once that happened, the device would freeze.
Upvotes: 0
Reputation: 36
Check if boost::interprocess supports Windows Mobile. They have facilities for creating memory-mapped files and using the memory to allocate any piece of data you want:
Upvotes: 1
Reputation: 20609
You're using an anonymous file mapping (one without an actual file backing it). When you do this, the mapping is backed by the system page file. It is likely that the Mobile OS does not actually have a Page File because the "hard disk" is probably a flash device. It's generally a bad idea to do virtual memory paging to flash devices because the nature of virtual memory means a high volume of writes which can quickly burn out flash (especially older types).
This seems to be backed up by the number of iterations you're getting. It looks like you're able to map up to around 60% of the total memory on your device.
You can probably get this to work with larger sections if you open a real file (using OpenFile
) and map that rather than using INVALID_FILE_HANDLE
in CreateFileMapping
. But be careful of your flash storage (and performance!) if you're going to be writing to your file mapping very much.
Upvotes: 0