CodeProject.ObjectPool 6.5.0

Object Pool

License: MIT Donate Docs NuGet version NuGet downloads

standard-readme compliant GitLab pipeline status Quality gate Code coverage Renovate enabled

A generic, concurrent, portable and flexible Object Pool for .NET, completely based on the Code Project article of Ofir Makmal.

Library is feature complete and no further development is planned on this project, except for routine maintenance and bug fixes.

Original source code has been modified, in order to introduce:

  • A Parameterized Object Pool, already drafted by Ofir Makmal in the comments of the article.
  • A Timed Object Pool, where objects are automatically removed after a period of inactivity.
  • Memory Stream and String Builder pools.
    • For use cases which might involve very large memory streams, I suggest to use the Microsoft.IO.RecyclableMemoryStream library from Microsoft. It eliminates Large Object Heap allocations, which this library does not do.

Moreover, a few unit tests have been added, in order to improve code reliability, and a lot of other small changes have also been applied.

Of course, all modified source code is freely available in this repository.

Many thanks to Ofir Makmal for his great work.

Table of Contents

Install

NuGet package CodeProject.ObjectPool is available for download:

dotnet add package CodeProject.ObjectPool

An adapter for Microsoft.Extensions.ObjectPool is also available on NuGet:

dotnet add package CodeProject.ObjectPool.MicrosoftExtensionsAdapter

Usage

Quick and dirty example:

/// <summary>
///   Example usages of ObjectPool.
/// </summary>
internal static class Program
{
    /// <summary>
    ///   Example usages of ObjectPool.
    /// </summary>
    private static void Main()
    {
        // Creating a pool with a maximum size of 25, using custom Factory method to create and
        // instance of ExpensiveResource.
        var pool = new ObjectPool<ExpensiveResource>(25, () => new ExpensiveResource(/* resource specific initialization */));

        using (var resource = pool.GetObject())
        {
            // Using the resource...
            resource.DoStuff();
        } // Exiting the using scope will return the object back to the pool.

        // Creating a pool with wrapper object for managing external resources, that is, classes
        // which cannot inherit from PooledObject.
        var newPool = new ObjectPool<PooledObjectWrapper<ExternalExpensiveResource>>(() =>
            new PooledObjectWrapper<ExternalExpensiveResource>(CreateNewResource())
            {
                OnReleaseResources = ExternalResourceReleaseResource,
                OnResetState = ExternalResourceResetState
            });

        using (var wrapper = newPool.GetObject())
        {
            // wrapper.InternalResource contains the object that you pooled.
            wrapper.InternalResource.DoOtherStuff();
        } // Exiting the using scope will return the object back to the pool.

        // Creates a pool where objects which have not been used for over 2 seconds will be
        // cleaned up by a dedicated thread.
        var timedPool = new TimedObjectPool<ExpensiveResource>(TimeSpan.FromSeconds(2));

        using (var resource = timedPool.GetObject())
        {
            // Using the resource...
            resource.DoStuff();
        } // Exiting the using scope will return the object back to the pool and record last usage.

        Console.WriteLine($"Timed pool size after 0 seconds: {timedPool.ObjectsInPoolCount}"); // Should be 1
        Thread.Sleep(TimeSpan.FromSeconds(4));
        Console.WriteLine($"Timed pool size after 4 seconds: {timedPool.ObjectsInPoolCount}"); // Should be 0

        // Adapts a timed pool to Microsoft Extensions abstraction.
        var mPool = ObjectPoolAdapter.CreateForPooledObject(timedPool);

        // Example usage of Microsoft pool.
        var mResource = mPool.Get();
        Debug.Assert(mResource != null);
        mPool.Return(mResource);

        // Adapts a new pool to Microsoft Extensions abstraction. This example shows how to adapt
        // when object type does not extend PooledObject.
        var mPool2 = ObjectPoolAdapter.Create(new ObjectPool<PooledObjectWrapper<MemoryStream>>(
            () => PooledObjectWrapper.Create(new MemoryStream())));

        // Example usage of second Microsoft pool.
        var mResource2 = mPool2.Get();
        Debug.Assert(mResource2 != null);
        mPool2.Return(mResource2);

        Console.Read();
    }

    private static ExternalExpensiveResource CreateNewResource()
    {
        return new ExternalExpensiveResource();
    }

    public static void ExternalResourceResetState(ExternalExpensiveResource resource)
    {
        // External Resource reset state code.
    }

    public static void ExternalResourceReleaseResource(ExternalExpensiveResource resource)
    {
        // External Resource release code.
    }
}

internal sealed class ExpensiveResource : PooledObject
{
    public ExpensiveResource()
    {
        OnReleaseResources = () =>
        {
            // Called if the resource needs to be manually cleaned before the memory is reclaimed.
        };

        OnResetState = () =>
        {
            // Called if the resource needs resetting before it is getting back into the pool.
        };
    }

    public void DoStuff()
    {
        // Do some work here, for example.
    }
}

internal sealed class ExternalExpensiveResource
{
    public void DoOtherStuff()
    {
        // Do some work here, for example.
    }
}

Async support

Starting from v4, Object Pool supports async pooled object initialization. Therefore, objects can be retrieved in two ways:

obj = pool.GetObject();
obj = await pool.GetObjectAsync();

Those methods depend on the factory method specified during pool initialization. Because making async factories "sync" is usually a problem, which can lead to deadlocks, we have the following situation:

Factory type GetObject GeObjectAsync
Not specified OK OK, uses a result task
Sync OK OK, uses a result task
Async KO, throws an exception OK

So, to sum it up:

  • If a sync factory is specified, both retrieval methods can be used.
  • If an async factory is specified, only the async retrieval can be used.

Maintainers

@pomma89.

Contributing

MRs accepted.

Small note: If editing the README, please conform to the standard-readme specification.

Editing

Visual Studio Code, with Remote Containers extension, is the recommended way to work on this project.

A development container has been configured with all required tools.

Visual Studio Community is also supported and an updated solution file, object-pool.sln, has been provided.

Restoring dependencies

When opening the development container, dependencies should be automatically restored.

Anyway, dependencies can be restored with following command:

dotnet restore

Running tests

Tests can be run with following command:

dotnet test

Tests can also be run with following command, which collects coverage information:

./build.sh --target run-tests

License

MIT © 2013-2023 PommaLabs Team and Contributors

Showing the top 20 packages that depend on CodeProject.ObjectPool.

Packages Downloads
Finsa.Caravan.Common.Runtime
A long description of the package. This shows up in the right pane of the Add Package Dialog as well as in the Package Manager Console when listing packages using the Get-Package command. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
136
Finsa.Caravan.Common.Runtime
A long description of the package. This shows up in the right pane of the Add Package Dialog as well as in the Package Manager Console when listing packages using the Get-Package command. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
44
Finsa.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
30
Finsa.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
142
Finsa.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
26
Finsa.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
46
PommaLabs.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
40
PommaLabs.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
140
PommaLabs.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
27
PommaLabs.CodeServices.Common
CodeServices.Common - .NET component with generic utilities. THIS PACKAGE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE PACKAGE OR THE USE OR OTHER DEALINGS IN THE PACKAGE.
48
PommaLabs.KVLite
A simple, timed and persistent key-value store based on SQLite. KVLite offers both a persistent and an in-memory implementation of that kind of store.
40
PommaLabs.KVLite
KVLite is a partition-based key-value cache built for SQL RDBMSs. This package contains caching interfaces, data models and core implementations.
36
PommaLabs.KVLite
KVLite is a partition-based key-value cache built for SQL RDBMSs. This package contains caching interfaces, data models and core implementations.
243
PommaLabs.KVLite
KVLite is a partition-based key-value cache built for SQL. KVLite can be stored either in persistent or volatile fashion, and each key/value pair can have its own lifetime and refresh mode. This package contains the dependencies needed by KVLite at runtime.
131
PommaLabs.KVLite
KVLite is a partition-based key-value cache built for SQL. KVLite can be stored either in persistent or volatile fashion, and each key/value pair can have its own lifetime and refresh mode. This package contains the dependencies needed by KVLite at runtime.
46
PommaLabs.KVLite
Very, very simple key value store based on SQLite.
27
PommaLabs.KVLite.Core
A simple, timed and persistent key-value store based on SQLite. KVLite offers both a persistent and an in-memory implementation of that kind of store. This package contains the core references for KVLite.
27
PommaLabs.KVLite.Core
KVLite is a partition-based key-value cache built for SQL RDBMSs. This package contains core implementations and base classes.
30
PommaLabs.KVLite.Core
KVLite is a partition-based key-value cache built for SQL RDBMSs. This package contains core implementations and base classes.
39
PommaLabs.KVLite.Core
KVLite is a partition-based key-value cache built for SQL RDBMSs. This package contains core implementations and base classes.
68

https://gitlab.com/pommalabs/codeproject/object-pool/-/releases

.NET 8.0

  • No dependencies.

.NET Standard 2.0

  • No dependencies.

Version Downloads Last updated
6.5.0 23 03/11/2024
6.4.0 19 02/07/2024
6.3.0 17 02/07/2024
6.2.0 17 02/07/2024
6.1.1 20 02/07/2024
6.1.0 23 02/07/2024
6.0.0 25 02/07/2024
5.0.5 22 02/07/2024
5.0.4 19 02/07/2024
5.0.3 24 02/07/2024
5.0.2 26 02/07/2024
5.0.1 25 02/07/2024
5.0.0 23 02/07/2024
4.0.2 218 07/04/2020
4.0.1 66 06/26/2020
3.2.4 19 02/07/2024
3.2.3 24 02/07/2024
3.2.2 24 02/07/2024
3.2.1 24 02/07/2024
3.2.0 28 02/07/2024
3.1.1 25 02/07/2024
3.1.0 22 02/07/2024
3.0.3 24 02/10/2020
3.0.2 26 02/10/2020
2.2.2 132 02/10/2020
2.2.1 24 02/10/2020
2.1.1 42 02/10/2020
2.1.0 24 02/10/2020
2.0.5 26 02/10/2020
2.0.4 30 02/10/2020
2.0.3 24 02/10/2020
2.0.2 29 02/10/2020
2.0.1 25 02/10/2020
1.10.1 24 02/10/2020
1.9.3 26 02/10/2020
1.9.2 24 02/10/2020
1.9.1 23 02/10/2020
1.9.0 23 02/10/2020
1.8.0 25 02/10/2020
1.7.0 25 02/07/2024
1.6.0 23 02/07/2024
1.5.0 24 02/07/2024
1.3.5 25 02/07/2024
1.3.3 25 02/07/2024
1.3.1 28 02/10/2020
1.3.0 26 02/07/2024
1.0.8 24 02/07/2024
1.0.6 31 04/09/2021
1.0.5 0 08/19/2014
1.0.4 0 08/18/2014