You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@ -0,0 +1,116 @@
|
||||
//------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//------------------------------------------------------------
|
||||
namespace System.ServiceModel.Channels
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime;
|
||||
|
||||
// This is the base object pool class which manages objects in a FIFO queue. The objects are
|
||||
// created through the provided Func<T> createObjectFunc. The main purpose for this class is
|
||||
// to get better memory usage for Garbage Collection (GC) when part or all of an object is
|
||||
// regularly pinned. Constantly creating such objects can cause large Gen0 Heap fragmentation
|
||||
// and thus high memory usage pressure. The pooled objects are first created in Gen0 heaps and
|
||||
// would be eventually moved to a more stable segment which would prevent the fragmentation
|
||||
// to happen.
|
||||
//
|
||||
// The objects are created in batches for better localization of the objects. Here are the
|
||||
// parameters that control the behavior of creation/removal:
|
||||
//
|
||||
// batchAllocCount: number of objects to be created at the same time when new objects are needed
|
||||
//
|
||||
// createObjectFunc: func delegate that is used to create objects by sub-classes.
|
||||
//
|
||||
// maxFreeCount: max number of free objects the queue can store. This is to make sure the memory
|
||||
// usage is bounded.
|
||||
//
|
||||
abstract class QueuedObjectPool<T>
|
||||
{
|
||||
Queue<T> objectQueue;
|
||||
bool isClosed;
|
||||
int batchAllocCount;
|
||||
int maxFreeCount;
|
||||
|
||||
protected void Initialize(int batchAllocCount, int maxFreeCount)
|
||||
{
|
||||
if (batchAllocCount <= 0)
|
||||
{
|
||||
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("batchAllocCount"));
|
||||
}
|
||||
|
||||
Fx.Assert(batchAllocCount <= maxFreeCount, "batchAllocCount cannot be greater than maxFreeCount");
|
||||
this.batchAllocCount = batchAllocCount;
|
||||
this.maxFreeCount = maxFreeCount;
|
||||
this.objectQueue = new Queue<T>(batchAllocCount);
|
||||
}
|
||||
|
||||
object ThisLock
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.objectQueue;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual bool Return(T value)
|
||||
{
|
||||
lock (ThisLock)
|
||||
{
|
||||
if (this.objectQueue.Count < this.maxFreeCount && ! this.isClosed)
|
||||
{
|
||||
this.objectQueue.Enqueue(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public T Take()
|
||||
{
|
||||
lock (ThisLock)
|
||||
{
|
||||
Fx.Assert(!this.isClosed, "Cannot take an item from closed QueuedObjectPool");
|
||||
|
||||
if (this.objectQueue.Count == 0)
|
||||
{
|
||||
AllocObjects();
|
||||
}
|
||||
|
||||
return this.objectQueue.Dequeue();
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
lock (ThisLock)
|
||||
{
|
||||
foreach (T item in this.objectQueue)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
this.CleanupItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
this.objectQueue.Clear();
|
||||
this.isClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void CleanupItem(T item)
|
||||
{
|
||||
}
|
||||
|
||||
protected abstract T Create();
|
||||
|
||||
void AllocObjects()
|
||||
{
|
||||
Fx.Assert(this.objectQueue.Count == 0, "The object queue must be empty for new allocations");
|
||||
for (int i = 0; i < batchAllocCount; i++)
|
||||
{
|
||||
this.objectQueue.Enqueue(Create());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user