Commit fba9ebd9 authored by Milo Yip's avatar Milo Yip Committed by GitHub

Merge pull request #776 from miloyip/issue728_threadsafe

Remove singletons in schema classes
parents 59bcebbf bf0cc7be
...@@ -349,6 +349,7 @@ public: ...@@ -349,6 +349,7 @@ public:
Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
allocator_(allocator), allocator_(allocator),
typeless_(schemaDocument->GetTypeless()),
enum_(), enum_(),
enumCount_(), enumCount_(),
not_(), not_(),
...@@ -453,7 +454,7 @@ public: ...@@ -453,7 +454,7 @@ public:
for (SizeType i = 0; i < propertyCount_; i++) { for (SizeType i = 0; i < propertyCount_; i++) {
new (&properties_[i]) Property(); new (&properties_[i]) Property();
properties_[i].name = allProperties[i]; properties_[i].name = allProperties[i];
properties_[i].schema = GetTypeless(); properties_[i].schema = typeless_;
} }
} }
} }
...@@ -575,9 +576,7 @@ public: ...@@ -575,9 +576,7 @@ public:
} }
~Schema() { ~Schema() {
if (allocator_) { AllocatorType::Free(enum_);
allocator_->Free(enum_);
}
if (properties_) { if (properties_) {
for (SizeType i = 0; i < propertyCount_; i++) for (SizeType i = 0; i < propertyCount_; i++)
properties_[i].~Property(); properties_[i].~Property();
...@@ -592,7 +591,7 @@ public: ...@@ -592,7 +591,7 @@ public:
#if RAPIDJSON_SCHEMA_HAS_REGEX #if RAPIDJSON_SCHEMA_HAS_REGEX
if (pattern_) { if (pattern_) {
pattern_->~RegexType(); pattern_->~RegexType();
allocator_->Free(pattern_); AllocatorType::Free(pattern_);
} }
#endif #endif
} }
...@@ -610,12 +609,12 @@ public: ...@@ -610,12 +609,12 @@ public:
else if (additionalItemsSchema_) else if (additionalItemsSchema_)
context.valueSchema = additionalItemsSchema_; context.valueSchema = additionalItemsSchema_;
else if (additionalItems_) else if (additionalItems_)
context.valueSchema = GetTypeless(); context.valueSchema = typeless_;
else else
RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
} }
else else
context.valueSchema = GetTypeless(); context.valueSchema = typeless_;
context.arrayElementIndex++; context.arrayElementIndex++;
} }
...@@ -792,7 +791,7 @@ public: ...@@ -792,7 +791,7 @@ public:
if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
if (context.patternPropertiesSchemaCount > 0) { if (context.patternPropertiesSchemaCount > 0) {
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
context.valueSchema = GetTypeless(); context.valueSchema = typeless_;
context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
} }
else else
...@@ -807,7 +806,7 @@ public: ...@@ -807,7 +806,7 @@ public:
if (additionalPropertiesSchema_) { if (additionalPropertiesSchema_) {
if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
context.valueSchema = GetTypeless(); context.valueSchema = typeless_;
context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
} }
else else
...@@ -815,7 +814,7 @@ public: ...@@ -815,7 +814,7 @@ public:
return true; return true;
} }
else if (additionalProperties_) { else if (additionalProperties_) {
context.valueSchema = GetTypeless(); context.valueSchema = typeless_;
return true; return true;
} }
...@@ -949,11 +948,6 @@ private: ...@@ -949,11 +948,6 @@ private:
SizeType count; SizeType count;
}; };
static const SchemaType* GetTypeless() {
static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
return &typeless;
}
template <typename V1, typename V2> template <typename V1, typename V2>
void AddUniqueElement(V1& a, const V2& v) { void AddUniqueElement(V1& a, const V2& v) {
for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
...@@ -1219,6 +1213,7 @@ private: ...@@ -1219,6 +1213,7 @@ private:
}; };
AllocatorType* allocator_; AllocatorType* allocator_;
const SchemaType* typeless_;
uint64_t* enum_; uint64_t* enum_;
SizeType enumCount_; SizeType enumCount_;
SchemaArray allOf_; SchemaArray allOf_;
...@@ -1344,12 +1339,16 @@ public: ...@@ -1344,12 +1339,16 @@ public:
allocator_(allocator), allocator_(allocator),
ownAllocator_(), ownAllocator_(),
root_(), root_(),
typeless_(),
schemaMap_(allocator, kInitialSchemaMapSize), schemaMap_(allocator, kInitialSchemaMapSize),
schemaRef_(allocator, kInitialSchemaRefSize) schemaRef_(allocator, kInitialSchemaRefSize)
{ {
if (!allocator_) if (!allocator_)
ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator());
typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
// Generate root schema, it will call CreateSchema() to create sub-schemas, // Generate root schema, it will call CreateSchema() to create sub-schemas,
// And call AddRefSchema() if there are $ref. // And call AddRefSchema() if there are $ref.
CreateSchemaRecursive(&root_, PointerType(), document, document); CreateSchemaRecursive(&root_, PointerType(), document, document);
...@@ -1367,8 +1366,8 @@ public: ...@@ -1367,8 +1366,8 @@ public:
} }
} }
else if (refEntry->schema) else if (refEntry->schema)
*refEntry->schema = SchemaType::GetTypeless(); *refEntry->schema = typeless_;
refEntry->~SchemaRefEntry(); refEntry->~SchemaRefEntry();
} }
...@@ -1384,12 +1383,14 @@ public: ...@@ -1384,12 +1383,14 @@ public:
allocator_(rhs.allocator_), allocator_(rhs.allocator_),
ownAllocator_(rhs.ownAllocator_), ownAllocator_(rhs.ownAllocator_),
root_(rhs.root_), root_(rhs.root_),
typeless_(rhs.typeless_),
schemaMap_(std::move(rhs.schemaMap_)), schemaMap_(std::move(rhs.schemaMap_)),
schemaRef_(std::move(rhs.schemaRef_)) schemaRef_(std::move(rhs.schemaRef_))
{ {
rhs.remoteProvider_ = 0; rhs.remoteProvider_ = 0;
rhs.allocator_ = 0; rhs.allocator_ = 0;
rhs.ownAllocator_ = 0; rhs.ownAllocator_ = 0;
rhs.typeless_ = 0;
} }
#endif #endif
...@@ -1398,6 +1399,11 @@ public: ...@@ -1398,6 +1399,11 @@ public:
while (!schemaMap_.Empty()) while (!schemaMap_.Empty())
schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry(); schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
if (typeless_) {
typeless_->~SchemaType();
Allocator::Free(typeless_);
}
RAPIDJSON_DELETE(ownAllocator_); RAPIDJSON_DELETE(ownAllocator_);
} }
...@@ -1432,7 +1438,7 @@ private: ...@@ -1432,7 +1438,7 @@ private:
void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
if (schema) if (schema)
*schema = SchemaType::GetTypeless(); *schema = typeless_;
if (v.GetType() == kObjectType) { if (v.GetType() == kObjectType) {
const SchemaType* s = GetSchema(pointer); const SchemaType* s = GetSchema(pointer);
...@@ -1519,6 +1525,8 @@ private: ...@@ -1519,6 +1525,8 @@ private:
return PointerType(); return PointerType();
} }
const SchemaType* GetTypeless() const { return typeless_; }
static const size_t kInitialSchemaMapSize = 64; static const size_t kInitialSchemaMapSize = 64;
static const size_t kInitialSchemaRefSize = 64; static const size_t kInitialSchemaRefSize = 64;
...@@ -1526,6 +1534,7 @@ private: ...@@ -1526,6 +1534,7 @@ private:
Allocator *allocator_; Allocator *allocator_;
Allocator *ownAllocator_; Allocator *ownAllocator_;
const SchemaType* root_; //!< Root schema. const SchemaType* root_; //!< Root schema.
SchemaType* typeless_;
internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
}; };
...@@ -1579,11 +1588,11 @@ public: ...@@ -1579,11 +1588,11 @@ public:
: :
schemaDocument_(&schemaDocument), schemaDocument_(&schemaDocument),
root_(schemaDocument.GetRoot()), root_(schemaDocument.GetRoot()),
outputHandler_(GetNullHandler()),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
schemaStack_(allocator, schemaStackCapacity), schemaStack_(allocator, schemaStackCapacity),
documentStack_(allocator, documentStackCapacity), documentStack_(allocator, documentStackCapacity),
outputHandler_(CreateNullHandler()),
valid_(true) valid_(true)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, depth_(0) , depth_(0)
...@@ -1607,11 +1616,12 @@ public: ...@@ -1607,11 +1616,12 @@ public:
: :
schemaDocument_(&schemaDocument), schemaDocument_(&schemaDocument),
root_(schemaDocument.GetRoot()), root_(schemaDocument.GetRoot()),
outputHandler_(outputHandler),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
schemaStack_(allocator, schemaStackCapacity), schemaStack_(allocator, schemaStackCapacity),
documentStack_(allocator, documentStackCapacity), documentStack_(allocator, documentStackCapacity),
outputHandler_(outputHandler),
nullHandler_(0),
valid_(true) valid_(true)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, depth_(0) , depth_(0)
...@@ -1622,6 +1632,10 @@ public: ...@@ -1622,6 +1632,10 @@ public:
//! Destructor. //! Destructor.
~GenericSchemaValidator() { ~GenericSchemaValidator() {
Reset(); Reset();
if (nullHandler_) {
nullHandler_->~OutputHandler();
StateAllocator::Free(nullHandler_);
}
RAPIDJSON_DELETE(ownStateAllocator_); RAPIDJSON_DELETE(ownStateAllocator_);
} }
...@@ -1795,11 +1809,11 @@ private: ...@@ -1795,11 +1809,11 @@ private:
: :
schemaDocument_(&schemaDocument), schemaDocument_(&schemaDocument),
root_(root), root_(root),
outputHandler_(GetNullHandler()),
stateAllocator_(allocator), stateAllocator_(allocator),
ownStateAllocator_(0), ownStateAllocator_(0),
schemaStack_(allocator, schemaStackCapacity), schemaStack_(allocator, schemaStackCapacity),
documentStack_(allocator, documentStackCapacity), documentStack_(allocator, documentStackCapacity),
outputHandler_(CreateNullHandler()),
valid_(true) valid_(true)
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
, depth_(depth) , depth_(depth)
...@@ -1827,8 +1841,8 @@ private: ...@@ -1827,8 +1841,8 @@ private:
const SchemaType** sa = CurrentContext().patternPropertiesSchemas; const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
bool valueUniqueness = CurrentContext().valueUniqueness; bool valueUniqueness = CurrentContext().valueUniqueness;
if (CurrentContext().valueSchema) RAPIDJSON_ASSERT(CurrentContext().valueSchema);
PushSchema(*CurrentContext().valueSchema); PushSchema(*CurrentContext().valueSchema);
if (count > 0) { if (count > 0) {
CurrentContext().objectPatternValidatorType = patternValidatorType; CurrentContext().objectPatternValidatorType = patternValidatorType;
...@@ -1913,20 +1927,20 @@ private: ...@@ -1913,20 +1927,20 @@ private:
Context& CurrentContext() { return *schemaStack_.template Top<Context>(); } Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); } const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
static OutputHandler& GetNullHandler() { OutputHandler& CreateNullHandler() {
static OutputHandler nullHandler; return *(nullHandler_ = static_cast<OutputHandler*>(stateAllocator_->Malloc(sizeof(OutputHandler))));
return nullHandler;
} }
static const size_t kDefaultSchemaStackCapacity = 1024; static const size_t kDefaultSchemaStackCapacity = 1024;
static const size_t kDefaultDocumentStackCapacity = 256; static const size_t kDefaultDocumentStackCapacity = 256;
const SchemaDocumentType* schemaDocument_; const SchemaDocumentType* schemaDocument_;
const SchemaType& root_; const SchemaType& root_;
OutputHandler& outputHandler_;
StateAllocator* stateAllocator_; StateAllocator* stateAllocator_;
StateAllocator* ownStateAllocator_; StateAllocator* ownStateAllocator_;
internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) internal::Stack<StateAllocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch) internal::Stack<StateAllocator> documentStack_; //!< stack to store the current path of validating document (Ch)
OutputHandler& outputHandler_;
OutputHandler* nullHandler_;
bool valid_; bool valid_;
#if RAPIDJSON_SCHEMA_VERBOSE #if RAPIDJSON_SCHEMA_VERBOSE
unsigned depth_; unsigned depth_;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment