There should be no problem constructing new instances of Tag,
Anchor and TagDirectives in separate threads anymore. D:YAML still is not thread safe itself, though (it's the user's responsibility to handle synchronization when working with a single node from two threads, for example).
This commit is contained in:
parent
765b74ffca
commit
23290239a7
|
@ -162,7 +162,7 @@ struct Node
|
||||||
Node.Pair[], Node[], YAMLObject) Value;
|
Node.Pair[], Node[], YAMLObject) Value;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//Stored value.
|
///Stored value.
|
||||||
Value value_;
|
Value value_;
|
||||||
///Start position of the node.
|
///Start position of the node.
|
||||||
Mark startMark_;
|
Mark startMark_;
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
///Shared object.
|
///Shared object.
|
||||||
module dyaml.sharedobject;
|
module dyaml.sharedobject;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixin for shared objects (need a better name).
|
* Mixin for shared objects (need a better name).
|
||||||
*
|
*
|
||||||
|
@ -18,65 +19,92 @@ module dyaml.sharedobject;
|
||||||
* and when there are many instances of a data type that are mostly
|
* and when there are many instances of a data type that are mostly
|
||||||
* duplicates (e.g. tags).
|
* duplicates (e.g. tags).
|
||||||
*
|
*
|
||||||
* Disadvantage is, this is not thread-safe (and neither is D:YAML, at the
|
* This is not the most elegant way to store the extra data and might change in future.
|
||||||
* moment). That might be fixed in futurere, though.
|
|
||||||
*
|
|
||||||
* This is not the most elegant way to store the extra data and change in future.
|
|
||||||
*/
|
*/
|
||||||
template SharedObject(T, MixedIn)
|
template SharedObject(T, MixedIn)
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
///Index of the object in objects_.
|
///This class stores the data that is shared between the objects.
|
||||||
|
class SharedData
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* Reference count.
|
||||||
|
*
|
||||||
|
* When this reaches zero, objects_ are cleared. This is not
|
||||||
|
* the number of shared objects, but rather of objects using this kind
|
||||||
|
* of shared object. This is used e.g. with Anchor, but not with Tag
|
||||||
|
* - tags can be stored by the user in Nodes so there is no way to know
|
||||||
|
* when there are no Tags anymore.
|
||||||
|
*/
|
||||||
|
int referenceCount_ = 0;
|
||||||
|
|
||||||
|
///All known objects of type T are in this array.
|
||||||
|
T[] objects_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
///Increment the reference count.
|
||||||
|
void addReference()
|
||||||
|
{
|
||||||
|
assert(referenceCount_ >= 0);
|
||||||
|
++referenceCount_;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Decrement the reference count and clear the constructed objects if zero.
|
||||||
|
void removeReference()
|
||||||
|
{
|
||||||
|
--referenceCount_;
|
||||||
|
assert(referenceCount_ >= 0);
|
||||||
|
if(referenceCount_ == 0)
|
||||||
|
{
|
||||||
|
clear(objects_);
|
||||||
|
objects_ = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Add an object and return its index.
|
||||||
|
uint add(ref T object)
|
||||||
|
{
|
||||||
|
foreach(uint index, ref T known; objects_)
|
||||||
|
{
|
||||||
|
if(object == known)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
objects_ ~= object;
|
||||||
|
return cast(uint)objects_.length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
///Get the object at specified object.
|
||||||
|
@property T get(in uint index)
|
||||||
|
{
|
||||||
|
return objects_[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///Index of the object in data_.
|
||||||
uint index_ = uint.max;
|
uint index_ = uint.max;
|
||||||
|
|
||||||
/**
|
///Stores the actual objects.
|
||||||
* Reference count.
|
static __gshared SharedData data_;
|
||||||
*
|
|
||||||
* When this reaches zero, objects_ are cleared. This count is not
|
|
||||||
* the number of shared objects, but rather of objects using this kind
|
|
||||||
* of shared object. This is used e.g. with Anchor, but not with Tag
|
|
||||||
* - tags can be stored by the user in Nodes so there is no way to know
|
|
||||||
* when there are no Tags anymore.
|
|
||||||
*/
|
|
||||||
static int referenceCount_ = 0;
|
|
||||||
|
|
||||||
/**
|
static this()
|
||||||
* All known objects of this type are in this array.
|
|
||||||
*
|
|
||||||
* Note that this is not shared among threads.
|
|
||||||
* Working the same YAML file in multiple threads is NOT safe with D:YAML.
|
|
||||||
*/
|
|
||||||
static T[] objects_;
|
|
||||||
|
|
||||||
///Add a new object, checking if identical object already exists.
|
|
||||||
void add(ref T object)
|
|
||||||
{
|
{
|
||||||
foreach(uint index, known; objects_)
|
data_ = new SharedData;
|
||||||
{
|
|
||||||
if(object == known)
|
|
||||||
{
|
|
||||||
index_ = index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
index_ = cast(uint)objects_.length;
|
|
||||||
objects_ ~= object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
///Increment the reference count.
|
///Increment the reference count.
|
||||||
static void addReference()
|
static void addReference()
|
||||||
{
|
{
|
||||||
assert(referenceCount_ >= 0);
|
synchronized(data_){data_.addReference();}
|
||||||
++referenceCount_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Decrement the reference count and clear the constructed objects if zero.
|
///Decrement the reference count and clear the constructed objects if zero.
|
||||||
static void removeReference()
|
static void removeReference()
|
||||||
{
|
{
|
||||||
--referenceCount_;
|
synchronized(data_){data_.removeReference();}
|
||||||
assert(referenceCount_ >= 0);
|
|
||||||
if(referenceCount_ == 0){objects_ = [];}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///Get the object.
|
///Get the object.
|
||||||
|
@ -84,7 +112,9 @@ template SharedObject(T, MixedIn)
|
||||||
in{assert(!isNull());}
|
in{assert(!isNull());}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
return objects_[index_];
|
T result;
|
||||||
|
synchronized(data_){result = data_.get(index_);}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
///Test for equality with another object.
|
///Test for equality with another object.
|
||||||
|
@ -95,5 +125,12 @@ template SharedObject(T, MixedIn)
|
||||||
|
|
||||||
///Is this object null (invalid)?
|
///Is this object null (invalid)?
|
||||||
bool isNull() const {return index_ == uint.max;}
|
bool isNull() const {return index_ == uint.max;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
///Add a new object, checking if identical object already exists.
|
||||||
|
void add(ref T object)
|
||||||
|
{
|
||||||
|
synchronized(data_){index_ = data_.add(object);}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue