Removed experimental ValueAllocator, it caused static initialization/destruction order issues (bug #2934500). The DefaultValueAllocator has been inlined in code.

This commit is contained in:
Baptiste Lepilleur 2010-03-13 13:10:27 +00:00
parent d38ba2a2cb
commit afd9cef928
5 changed files with 47 additions and 113 deletions

View File

@ -12,4 +12,10 @@
Notes: you need to setup the environment by running vcvars32.bat Notes: you need to setup the environment by running vcvars32.bat
(e.g. MSVC 2008 command prompt in start menu) before running scons. (e.g. MSVC 2008 command prompt in start menu) before running scons.
* Value
- Removed experimental ValueAllocator, it caused static
initialization/destruction order issues (bug #2934500).
The DefaultValueAllocator has been inlined in code.

View File

@ -26,7 +26,6 @@ namespace Json {
class ValueIterator; class ValueIterator;
class ValueConstIterator; class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP #ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueAllocator;
class ValueMapAllocator; class ValueMapAllocator;
class ValueInternalLink; class ValueInternalLink;
class ValueInternalArray; class ValueInternalArray;

View File

@ -513,26 +513,7 @@ namespace Json {
Args args_; Args args_;
}; };
/** \brief Experimental do not use: Allocator to customize member name and string value memory management done by Value.
*
* - makeMemberName() and releaseMemberName() are called to respectively duplicate and
* free an Json::objectValue member name.
* - duplicateStringValue() and releaseStringValue() are called similarly to
* duplicate and free a Json::stringValue value.
*/
class ValueAllocator
{
public:
enum { unknown = (unsigned)-1 };
virtual ~ValueAllocator();
virtual char *makeMemberName( const char *memberName ) = 0;
virtual void releaseMemberName( char *memberName ) = 0;
virtual char *duplicateStringValue( const char *value,
unsigned int length = unknown ) = 0;
virtual void releaseStringValue( char *value ) = 0;
};
#ifdef JSON_VALUE_USE_INTERNAL_MAP #ifdef JSON_VALUE_USE_INTERNAL_MAP
/** \brief Allocator to customize Value internal map. /** \brief Allocator to customize Value internal map.

View File

@ -415,7 +415,7 @@ ValueInternalMap::setNewItem( const char *key,
ValueInternalLink *link, ValueInternalLink *link,
BucketIndex index ) BucketIndex index )
{ {
char *duplicatedKey = valueAllocator()->makeMemberName( key ); char *duplicatedKey = makeMemberName( key );
++itemCount_; ++itemCount_;
link->keys_[index] = duplicatedKey; link->keys_[index] = duplicatedKey;
link->items_[index].setItemUsed(); link->items_[index].setItemUsed();

View File

@ -24,91 +24,39 @@ const Int Value::minInt = Int( ~(UInt(-1)/2) );
const Int Value::maxInt = Int( UInt(-1)/2 ); const Int Value::maxInt = Int( UInt(-1)/2 );
const UInt Value::maxUInt = UInt(-1); const UInt Value::maxUInt = UInt(-1);
// A "safe" implementation of strdup. Allow null pointer to be passed. /// Unknown size marker
// Also avoid warning on msvc80. enum { unknown = (unsigned)-1 };
//
//inline char *safeStringDup( const char *czstring )
//{
// if ( czstring )
// {
// const size_t length = (unsigned int)( strlen(czstring) + 1 );
// char *newString = static_cast<char *>( malloc( length ) );
// memcpy( newString, czstring, length );
// return newString;
// }
// return 0;
//}
//
//inline char *safeStringDup( const std::string &str )
//{
// if ( !str.empty() )
// {
// const size_t length = str.length();
// char *newString = static_cast<char *>( malloc( length + 1 ) );
// memcpy( newString, str.c_str(), length );
// newString[length] = 0;
// return newString;
// }
// return 0;
//}
ValueAllocator::~ValueAllocator()
/** Duplicates the specified string value.
* @param value Pointer to the string to duplicate. Must be zero-terminated if
* length is "unknown".
* @param length Length of the value. if equals to unknown, then it will be
* computed using strlen(value).
* @return Pointer on the duplicate instance of string.
*/
static inline char *
duplicateStringValue( const char *value,
unsigned int length = unknown )
{ {
if ( length == unknown )
length = (unsigned int)strlen(value);
char *newString = static_cast<char *>( malloc( length + 1 ) );
memcpy( newString, value, length );
newString[length] = 0;
return newString;
} }
class DefaultValueAllocator : public ValueAllocator
/** Free the string duplicated by duplicateStringValue().
*/
static inline void
releaseStringValue( char *value )
{ {
public: if ( value )
virtual ~DefaultValueAllocator() free( value );
{
}
virtual char *makeMemberName( const char *memberName )
{
return duplicateStringValue( memberName );
}
virtual void releaseMemberName( char *memberName )
{
releaseStringValue( memberName );
}
virtual char *duplicateStringValue( const char *value,
unsigned int length = unknown )
{
//@todo invesgate this old optimization
//if ( !value || value[0] == 0 )
// return 0;
if ( length == unknown )
length = (unsigned int)strlen(value);
char *newString = static_cast<char *>( malloc( length + 1 ) );
memcpy( newString, value, length );
newString[length] = 0;
return newString;
}
virtual void releaseStringValue( char *value )
{
if ( value )
free( value );
}
};
static ValueAllocator *&valueAllocator()
{
static DefaultValueAllocator defaultAllocator;
static ValueAllocator *valueAllocator = &defaultAllocator;
return valueAllocator;
} }
static struct DummyValueAllocatorInitializer {
DummyValueAllocatorInitializer()
{
valueAllocator(); // ensure valueAllocator() statics are initialized before main().
}
} dummyValueAllocatorInitializer;
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
@ -143,7 +91,7 @@ Value::CommentInfo::CommentInfo()
Value::CommentInfo::~CommentInfo() Value::CommentInfo::~CommentInfo()
{ {
if ( comment_ ) if ( comment_ )
valueAllocator()->releaseStringValue( comment_ ); releaseStringValue( comment_ );
} }
@ -151,11 +99,11 @@ void
Value::CommentInfo::setComment( const char *text ) Value::CommentInfo::setComment( const char *text )
{ {
if ( comment_ ) if ( comment_ )
valueAllocator()->releaseStringValue( comment_ ); releaseStringValue( comment_ );
JSON_ASSERT( text ); JSON_ASSERT( text );
JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /"); JSON_ASSERT_MESSAGE( text[0]=='\0' || text[0]=='/', "Comments must start with /");
// It seems that /**/ style comments are acceptable as well. // It seems that /**/ style comments are acceptable as well.
comment_ = valueAllocator()->duplicateStringValue( text ); comment_ = duplicateStringValue( text );
} }
@ -178,7 +126,7 @@ Value::CZString::CZString( int index )
} }
Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate ) Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
: cstr_( allocate == duplicate ? valueAllocator()->makeMemberName(cstr) : cstr_( allocate == duplicate ? duplicateStringValue(cstr)
: cstr ) : cstr )
, index_( allocate ) , index_( allocate )
{ {
@ -186,7 +134,7 @@ Value::CZString::CZString( const char *cstr, DuplicationPolicy allocate )
Value::CZString::CZString( const CZString &other ) Value::CZString::CZString( const CZString &other )
: cstr_( other.index_ != noDuplication && other.cstr_ != 0 : cstr_( other.index_ != noDuplication && other.cstr_ != 0
? valueAllocator()->makeMemberName( other.cstr_ ) ? duplicateStringValue( other.cstr_ )
: other.cstr_ ) : other.cstr_ )
, index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate) , index_( other.cstr_ ? (other.index_ == noDuplication ? noDuplication : duplicate)
: other.index_ ) : other.index_ )
@ -196,7 +144,7 @@ Value::CZString::CZString( const CZString &other )
Value::CZString::~CZString() Value::CZString::~CZString()
{ {
if ( cstr_ && index_ == duplicate ) if ( cstr_ && index_ == duplicate )
valueAllocator()->releaseMemberName( const_cast<char *>( cstr_ ) ); releaseStringValue( const_cast<char *>( cstr_ ) );
} }
void void
@ -348,7 +296,7 @@ Value::Value( const char *value )
, itemIsUsed_( 0 ) , itemIsUsed_( 0 )
#endif #endif
{ {
value_.string_ = valueAllocator()->duplicateStringValue( value ); value_.string_ = duplicateStringValue( value );
} }
@ -361,8 +309,8 @@ Value::Value( const char *beginValue,
, itemIsUsed_( 0 ) , itemIsUsed_( 0 )
#endif #endif
{ {
value_.string_ = valueAllocator()->duplicateStringValue( beginValue, value_.string_ = duplicateStringValue( beginValue,
UInt(endValue - beginValue) ); UInt(endValue - beginValue) );
} }
@ -374,8 +322,8 @@ Value::Value( const std::string &value )
, itemIsUsed_( 0 ) , itemIsUsed_( 0 )
#endif #endif
{ {
value_.string_ = valueAllocator()->duplicateStringValue( value.c_str(), value_.string_ = duplicateStringValue( value.c_str(),
(unsigned int)value.length() ); (unsigned int)value.length() );
} }
@ -400,7 +348,7 @@ Value::Value( const CppTL::ConstString &value )
, itemIsUsed_( 0 ) , itemIsUsed_( 0 )
#endif #endif
{ {
value_.string_ = valueAllocator()->duplicateStringValue( value, value.length() ); value_.string_ = duplicateStringValue( value, value.length() );
} }
# endif # endif
@ -434,7 +382,7 @@ Value::Value( const Value &other )
case stringValue: case stringValue:
if ( other.value_.string_ ) if ( other.value_.string_ )
{ {
value_.string_ = valueAllocator()->duplicateStringValue( other.value_.string_ ); value_.string_ = duplicateStringValue( other.value_.string_ );
allocated_ = true; allocated_ = true;
} }
else else
@ -481,7 +429,7 @@ Value::~Value()
break; break;
case stringValue: case stringValue:
if ( allocated_ ) if ( allocated_ )
valueAllocator()->releaseStringValue( value_.string_ ); releaseStringValue( value_.string_ );
break; break;
#ifndef JSON_VALUE_USE_INTERNAL_MAP #ifndef JSON_VALUE_USE_INTERNAL_MAP
case arrayValue: case arrayValue: