Boost logo

Boost :

Subject: Re: [boost] Proposal: Monotonic Containers - Comparison with boost::pool, boost::fast_pool and TBB
From: Christian Schladetsch (christian.schladetsch_at_[hidden])
Date: 2009-06-22 19:03:16


Hi Luke,

[...] I have two ideas. First, put a counter in monotonic that is
> incremented when allocations happen and decremented when deallocations
> happen. If the counter is ever zero you blow away all the buffers
> automatically.
>

This is a good idea; I'll add it. I currently keep track of allocation
counts for informative reasons only for debug builds.

> Second, you create a scoped object that encapsulates the idea of the
> monotonic storage's lifetime and delete the buffers when the object is
> destructed.

see
https://svn.boost.org/svn/boost/sandbox/monotonic/boost/monotonic/local.hpp.

monotonic::local<> storage;
{
     std::list<int, monotonic::allocator<int> > list; // uses local storage,
not global
}

Finally, you add a template parameter to monotonic to allow many programmers
> working in the same application to declare their own monotonic type that has
> separate buffers and lifetime from eachother.

see
https://svn.boost.org/svn/boost/sandbox/monotonic/boost/monotonic/region_allocator.hpp.
The nterface is:

        /// a monotonic region allocator uses a specified storage.
        /// Each region uses independent
        /// storage that may be used and reset.
        template <class T, size_t Region = 0>
        struct region_allocator;

This is used like:

    typedef std::list<int, monotonic::region_allocator<int, 0> > List;
    typedef std::list<int, monotonic::region_allocator<int, 42> > OtherList;
    // ....
    monotonic::reset_region<42>();

etc. Basically, it allows you to have up to
monotonic::DefaultSizes::MaxRegions of independantly controlled regions of
storage.

In this way managing the memory owned monotonic can be easy and safe. The
> only problem left is therefore misuse. I'm trying to understand the risk of
> misuse, and it looks like running out of memory is the primary risk.

I mentioned earlier that it may be beneficial to add introspection to debug
builds that warn about misuse, and I increasingly think it will be
necessary.

> Perhaps I missed this part of the discussion, but why is it named
> monotonic?

The name has been questioned earlier as well. The motivation for the name
came from the fact that memory usage only ever increases - monotonically.

I agree that the name is somewhat vague, especially considering that it can
be used as a general stack+heap storage system, as well as an allocator.

> I would think something that describes its intended usage would be better.
> boost::scratch_memory, for example. Anyone who keeps objects allocated
> with an allocator called scratch_memory around for the lifetime of his
> program has some obvious explaining to do.

I like this because it makes it clear that it is primarily for temporay use.
It also works for the following:

boost::scratch_memory::storage<> storage;
{
    string &str = storage.create<string>("spam");
    boost::array<Foo, 16> &foos = storage.create<boost::array<Foo, 16> >();
    storage.destroy(str);
    storage.destroy(foos);
}

The usage is a bit clearer than boost::monotonic::storage<>

> I also think that a more general interface would be to allow the user to
> supply and address and size of memory to use as the initial scratch memory
> with the automatic (on by default) ability to grow beyond that buffer if
> needed with system allocation on the heap using the chain.

This is a good idea and can be adopted. Currently, storage<StackSize,
MinHeapIncrement> uses the stack first, then the heap. You can of course
make it just on the stack with storage<N, 0> or just on the heap with
storage<0, N>.

However it could be made so that the first link in the chain is supplied by
the user. See
https://svn.boost.org/svn/boost/sandbox/monotonic/boost/monotonic/storage.hpp
.

> Thread safty should be controlled by a template parameter and enabled by
> default.

Currently, thread-safety is controlled by the allocator type:

monotonic::allocator<T> // single-threaded
monotonic::shared_allocator<T> // multi-threaded via mutex
monotonic::local_allocator<T> // uses thread-local-storage for the storage

Regards,
Christian


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk