Class Shared<T>
Provides a container that tracks the usage of a shared resource (such as a large memory allocation). Follow the Cloning pattern and use the Shared.DeepClone extension method instead of direct assignment to create long-lived references to the same shared resource.
Implements
Namespace: Microsoft.Psi
Assembly: Microsoft.Psi.dll
Syntax
public class Shared<T> : IDisposable where T : class
Type Parameters
Name | Description |
---|---|
T | The type of data held by this container. |
Remarks
The .Net model of delayed memory management via garbage collection is ill suited for frequent large allocations. The memory allocated for an object can only reused after the object is garbage collected. Since garbage collection is relatively infrequent, and independent of the lifespan of the allocated objects, the time interval between the object becoming available for garbage collection (that is, when nobody alive references it anymore) and the memory becoming available for reuse can be quite large. More importantly, the memory is only reclaimed as a result of a garbage collection pass, with a cost proportional to the number of objects allocated since the last garbage collection pass. The generational model of the .Net garbage collector mitigates this issue to some extent, but not enough to avoid large garbage collection pauses in memory-intensive streaming systems, e.g. when allocating video frames at frame rate. The Shared class is designed to provide full control over memory allocations, to make it possible to exchange buffers between concurrent components but also reuse them once they are not needed anymore. It uses explicit reference counting to decide when the memory can be released back to an allocation pool, without having to rely on the garbage collector. The behavior of Shared is as follows:
- when a Shared instance is instantiated, the reference count of the resource is set to 1.
- when a Shared instance is cloned (via Shared.DeepClone or Shared.AddRef), the reference count is incremented by 1.
- when a Shared instance is disposed (via Shared.Dispose or by the "using" keyword) the reference count is decremented by 1.
- the ref count is not affected when using the assignment operator (e.g. var copy = shared). Thus, for it to function properly, the handling of Shared instances requires following special rules:
- avoid using the assignment operator to capture references to a Shared instance beyond local scope.
- call myShared.AddRef() to create a new reference to the underlying resource, and remember to call Dispose when done with it.
- use myShared.DeepClone(ref this.myStoredCopy) to store a long-lived reference to a Shared instance in a class field. DeepClone will Dispose the target object first if needed, before cloning.
- there is no need to clone or AddRef when posting a Shared instance to a message stream.
- never store a long-lived reference to the underlying resource. Note that Shared doesn't provide any facilities for concurrent access to the underlying resource. Once a resource is wrapped in a Shared object, it should be considered read-only.
Properties
View SourceResource
Gets underlying resource.
Declaration
public T Resource { get; }
Property Value
Type | Description |
---|---|
T |
SharedPool
Gets the shared object pool.
Declaration
public SharedPool<T> SharedPool { get; }
Property Value
Type | Description |
---|---|
SharedPool<T> |
Methods
View SourceAddRef()
Add reference.
Declaration
public Shared<T> AddRef()
Returns
Type | Description |
---|---|
Shared<T> | Shared resource. |
Dispose()
Declaration
public void Dispose()
Finalize()
Finalizes an instance of the Shared<T> class.
Declaration
protected void Finalize()
ToString()
Declaration
public override string ToString()
Returns
Type | Description |
---|---|
String |
ToString(String, IFormatProvider)
Declaration
public string ToString(string format, IFormatProvider formatProvider)
Parameters
Type | Name | Description |
---|---|---|
String | format | |
IFormatProvider | formatProvider |
Returns
Type | Description |
---|---|
String |