[Jahshaka-cvs] SF.net SVN: openlibraries:[1472] trunk/src/openpluginlib/pl
Status: Beta
Brought to you by:
jahshaka
From: <tim...@us...> - 2009-05-25 14:05:20
|
Revision: 1472 http://openlibraries.svn.sourceforge.net/openlibraries/?rev=1472&view=rev Author: timdewhirst Date: 2009-05-25 14:05:04 +0000 (Mon, 25 May 2009) Log Message: ----------- OPL * clarify pool logic * add extra information to memory pre-amble to help catch freeing of non-pool memory * add dump of pool Modified Paths: -------------- trunk/src/openpluginlib/pl/pool.cpp trunk/src/openpluginlib/pl/pool.hpp Modified: trunk/src/openpluginlib/pl/pool.cpp =================================================================== --- trunk/src/openpluginlib/pl/pool.cpp 2009-05-12 09:42:33 UTC (rev 1471) +++ trunk/src/openpluginlib/pl/pool.cpp 2009-05-25 14:05:04 UTC (rev 1472) @@ -1,3 +1,4 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ // pool - A pooled memory allocator // Copyright (C) 2005-2007 Editopia Inc. @@ -5,9 +6,12 @@ // For more information, see http://www.openlibraries.org. #include "pool.hpp" +#include "log.hpp" // std #include <cstring> +#include <cassert> +#include <sstream> using namespace std; using namespace olib::openpluginlib; @@ -15,6 +19,8 @@ // Declaration of mutex OPENPLUGINLIB_DECLSPEC boost::mutex pool::mutex_; +const unsigned int POOL_COUNT = 31; + // Constructor creates 31 pools sized at 2^i pool::pool( ) { @@ -23,7 +29,7 @@ // Destroys pools pool::~pool( ) { - for( int i = 0; i < 31; i ++ ) + for( int i = 0; i < POOL_COUNT; i ++ ) { typedef std::vector< unsigned char * >::iterator iterator; for( iterator I = pools_[ i ].begin( ); I != pools_[ i ].end( ); ++I ) @@ -45,41 +51,81 @@ } // Singleton destructor + +static const char PREAMBLE_TEXT[] = { 'p', 'o', 'o', 'l' }; + +template < typename T > +int array_size( T& a ) { return sizeof( a )/sizeof( a[0] ); } + void pool::destroy( ) { delete get_instance( ); } +int preamble_size() +{ + return array_size( PREAMBLE_TEXT ) + sizeof( int ); +} + +void write_preamble( unsigned char* p, int index ) +{ + int s = array_size( PREAMBLE_TEXT ); + ::memcpy( p, PREAMBLE_TEXT, s ); + *(int*)(p+s) = index; +} + +bool is_valid_preamble( unsigned char* p ) +{ + int s = array_size( PREAMBLE_TEXT ); + return (::memcmp( p, PREAMBLE_TEXT, s ) == 0) && ( *(int*)(p+s) < POOL_COUNT ) ; +} + +int get_index( unsigned char* p ) +{ + if ( !is_valid_preamble( p ) ) + { + WARNING_LOG << "invalid preamble found"; + return -1; + } + + return *(int *)(p+array_size( PREAMBLE_TEXT )); +} + // Allocate memory >= size unsigned char *pool::malloc( int size ) { #ifdef HAVE_POOL - unsigned char *result = 0; + unsigned char *result = NULL; if ( size > 0 ) { // Account for index storage - size += sizeof(int); + size += preamble_size(); pool *self = get_instance( ); int index = 1; while ( ( 1 << index ) < size ) index ++; + boost::mutex::scoped_lock scoped_lock( mutex_ ); + int used = index; - while ( used < 31 && self->pools_[ index ].size( ) == 0 ) used ++; - if ( used == 31 ) used = index; + while ( used < POOL_COUNT && self->pools_[ used ].size( ) == 0 ) used ++; + if ( used == POOL_COUNT ) used = index; + if ( self->pools_[ used ].size( ) == 0 ) { result = new unsigned char[ 1 << index ]; if ( result != 0 ) { - *( int * )( result ) = index; - result += sizeof( int ); + write_preamble( result, index ); + result += preamble_size(); } } else { - result = *( self->pools_[ used ].end( ) - 1 ) + sizeof( int ); + result = *( self->pools_[ used ].end( ) - 1 ); + write_preamble( result, used ); + result += preamble_size(); self->pools_[ used ].pop_back( ); } } @@ -99,9 +145,9 @@ if ( chunk != 0 ) { // Account for index storage - size += sizeof(int); + size += preamble_size(); - int old_index = *( int * )( chunk - sizeof( int ) ); + int old_index = get_index( chunk - preamble_size() ); int index = 1; while ( ( 1 << index ) < size ) index ++; if ( old_index < index ) @@ -129,12 +175,33 @@ if ( chunk != 0 ) { pool *self = get_instance( ); - int index = *( int * )( chunk - sizeof( int ) ); + + chunk -= preamble_size(); + if ( !is_valid_preamble( chunk ) ) + { + WARNING_LOG << "possibly trying to recycle memory that wasn't allocated by pool"; + abort(); + return; + } + + int index = get_index( chunk ); boost::mutex::scoped_lock scoped_lock( mutex_ ); - self->pools_[ index ].push_back( chunk - sizeof( int ) ); + self->pools_[ index ].push_back( chunk ); } #else std::free( chunk ); #endif } +void pool::dump_state() +{ +#ifdef HAVE_POOL + std::stringstream ss; + + ss << "\npool counts:\n"; + for ( unsigned int i=0; i<POOL_COUNT; ++i ) + ss << " [" << i << "]: " << get_instance()->pools_[i].size() << "\n"; + + DEBUG_LOG << ss.str(); +#endif +} Modified: trunk/src/openpluginlib/pl/pool.hpp =================================================================== --- trunk/src/openpluginlib/pl/pool.hpp 2009-05-12 09:42:33 UTC (rev 1471) +++ trunk/src/openpluginlib/pl/pool.hpp 2009-05-25 14:05:04 UTC (rev 1472) @@ -1,3 +1,4 @@ +/* -*- mode: C++; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: t -*- */ // pool - A pooled memory allocator // Copyright (C) 2005-2007 Editopia Inc. @@ -21,28 +22,31 @@ class OPENPLUGINLIB_DECLSPEC pool { - private: - // Private constructor and destructor - pool( ); - ~pool( ); +private: + // Private constructor and destructor + pool( ); + ~pool( ); + + // Singleton accessor and destructor + static pool *get_instance( ); + static void destroy( ); + + // The boost pools + std::vector< unsigned char * > pools_[ 32 ]; + static boost::mutex mutex_; + +public: + // Provide a chunk >= size + static unsigned char *malloc( int size ); + + // Reallocate a chunk to a new size + static unsigned char *realloc( unsigned char *chunk, int size ); + + // Return a chunk to the pool + static void free( unsigned char *chunk ); - // Singleton accessor and destructor - static pool *get_instance( ); - static void destroy( ); - - // The boost pools - std::vector< unsigned char * > pools_[ 32 ]; - static boost::mutex mutex_; - - public: - // Provide a chunk >= size - static unsigned char *malloc( int size ); - - // Reallocate a chunk to a new size - static unsigned char *realloc( unsigned char *chunk, int size ); - - // Return a chunk to the pool - static void free( unsigned char *chunk ); + // dump some information about the pool + static void dump_state(); }; } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |