/* Copyright 2010-2014 MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections.Generic; namespace MongoDB.Bson.IO { /// /// Represents a pool of chunks used by BsonBuffer. /// public class BsonChunkPool { // private static fields private static BsonChunkPool __default = new BsonChunkPool(2048, 16 * 1024); // 32MiB of 16KiB chunks // private fields private readonly object _lock = new object(); private readonly Stack _chunks = new Stack(); private readonly int _maxPoolSize; private readonly int _chunkSize; // constructors /// /// Initializes a new instance of the class. /// /// The maximum number of chunks to keep in the pool. /// The size of each chunk. public BsonChunkPool(int maxPoolSize, int chunkSize) { _maxPoolSize = maxPoolSize; _chunkSize = chunkSize; } // public static properties /// /// Gets the default chunk pool. /// /// /// The default chunk pool. /// public static BsonChunkPool Default { get { return __default; } set { if (value == null) { throw new ArgumentNullException("Default"); } __default = value; } } // public properties /// /// Gets the chunk size. /// /// /// The chunk size. /// public int ChunkSize { get { return _chunkSize; } } /// /// Gets or sets the max pool size. /// public int MaxPoolSize { get { return _maxPoolSize; } } // internal methods /// /// Acquires a chunk. /// /// internal BsonChunk AcquireChunk() { lock (_lock) { if (_chunks.Count > 0) { return _chunks.Pop(); } } // release the lock before allocating memory var bytes = new byte[_chunkSize]; return new BsonChunk(bytes, this); } /// /// Releases a chunk. /// /// The chunk. internal void ReleaseChunk(BsonChunk chunk) { if (chunk.ReferenceCount != 0) { new BsonInternalException("A chunk is being returned to the pool and the reference count is not zero."); } lock (_lock) { if (_chunks.Count < _maxPoolSize) { _chunks.Push(chunk); } // otherwise just let it get garbage collected } } } }