In an embedded program I have a screen object that needs to manage a list of items to display. The initial list of items will be pulled from a simple DB on screen load and the list will be updated via "Add" and "Remove" events. This list needs to be sorted according to certain criteria. I am looking of a container class that can help me accomplish this. Furthermore there is no dynamic memory in the system so I need to have a memory pool of empty items that I can load into container and return to the free pool when I am done with the item.
Anyone know of anything appropriate in the C++ Standard Library or Boost? Or perhaps another solution?
why not use STL but provide your own allocator and deallocator, for example STL vector is defined as template<class T,class A = std::allocator<T>> vector {}, you can create and set your own allocator that request memory space from your memory pool.
as for memory allocator, you use existing memory allocator such as Hoard http://www.hoard.org/ , or Ned Allocator http://www.nedprod.com/programs/portable/nedmalloc/ which is quite high performance and good for embedded system.
If you use a standard container (such as std::map or std::set) you need to worry about different dynamic allocations: the allocation of the internal container data structures and the allocation of your own data you want to store in the container. The allocation of the internal data structures can be customized by supplying your own std::allocator (I'm sure you'll be able to find one fitting your needs, there are plenty of those available). The allocation of your own data structures needs to be handled separately, most commonly by implementing type specific new and delete operators. Scott Meyers has a nice article about this in one of his books.
Another solution would be to utilize Boost.Intrusive, a set of containers where all the internal data items needed for the container are stored in your own data structures (that's why they are called intrusive). This relieves you from having two different allocation schemes in place, as you need to worry about your own data allocation only.
Related
I want to create a custom allocator for a multimap that will allocate the elements in shared memory.I came across boost.interprocess but found it quite complicated to implement.Is there any other workaround ?
I will not give here any implementation, rather to give you some directions.
If your shared memory abstraction or region, for example start at adress void* shMemAddr and if you decide that your stl container to use shared memory,
what needs to be done is to make container allocate memory starting at shMemAddr and further, until there is available memory to allocate in your shared pool. You can implement that using any allocation strategy, for example using malloc or placement new. Further, to be available for your container to use your allocator you need to provide your allocator as template argument, for multimap it would be multimap::allocator_type
class Alloc = allocator > as fourth template argument, after less as compare function,and, for example, if you store in your multimap pairs of int,double as key,value pairs, it would likely be something like this
multimap<int,double,less<int>,CustomAlloc<pair<int,double>>>
Now, your CustomAlloc allocator need to satisfies concept of Allocators which encapsulate specific lowlevel memory management, especially, if shared memory is resource to be allocate in, you need to arrange proper allocation of memory in a multithreaded enviornment. That means that, first, you need some structure for evidence of used memory. It can be some chained data structure, for example, and implementations like that is pretty common, so you need to keep invariants of that structure consistent. What that means is if your structure for book keeping of used(or free) memory need to be updated after succesfull allocation or deallocation it needs to be done atomicaly, so thread which possibly try to allocate memory see only structure in states before CustomAllocator allocation job is started or after allocation job is finished. For example, your first choice to do that could be using mutex to protect data, avoid races and keep invariants. This is just directions, and considering write your own allocators is not very hard, I hope this will help as good starting point.
As far as I know, when a vector runs out of space the allocator is used to create new space. However, I want to create a custom resize policy that will remove the bottom 25% of elements instead and maintain the same size all the time. This is to build a cache that has limited space.
Is there a method or default functor I can override to get the behavior I want?
TL;DR, you are trying to use the wrong container.
The allocator is responsible for the allocation, deallocation etc. of the memory as required by the container. It is the responsibility of the container to implement the required semantics and it uses the allocators to assist it in doing so.
std::vector is probably not the best choice for the cache you describe, or at least not in its raw form.
You can look to boost (circular_buffer) as an alternative.
Given the vector you mention, you could also look to wrap that with the cache interface you desire, but changing the allocator is not the correct route. Changes to the allocator will leave the vector thinking there are valid objects in the "lower" 25% of the container, whilst the allocator has already removed them (or the memory to them).
I was looking into how custom containers are created, such as eastl's container and several other models and I see that they all use an "allocator", much like std::vector does with std::allocator. Which got me thinking, why do new implementations of a vector container use an allocator when they typically have an underlying memory management override for new and delete?
Being able to replace operator new() and operator delete() (and their array versions) at program level may be sufficient for small program. If you have programs consisting of many millions lines of code, running many different threads this isn't at all suitable. You often want or even need better control. To make the use of custom allocators effective, you also need to be able to allocate subobjects using the same objects as the outer allocator.
For example, consider the use of memory arena to be used when answering a request in some sort of a server which is probably running multiple threads. Getting memory from operator new() is probably fairly expensive because it involves allocating a lock and finding a suitable chunk of memory in a heap which is getting more and more fragmented. To avoid this, you just want to allocate a few chunks of memory (ideally just one but you may not know the needed size in advance) and put all objects there. An allocator can do this. To do so, you need to inform all entities allocating memory about this chunk of memory, i.e. you need to pass the allocator to everything possibly allocating memory. If you allocate e.g. a std::vector<std::string, A> the std::string objects should know about the allocator: just telling the std::vector<std::string, A> where and how to allocate memory isn't enough to avoid most memory allocations: you also need to tell it to the std::string (well, actually the std::basic_string<char, std::char_traits<char>, B> for a suitable allocator type B which is related to A).
That is, if you really mean to take control of your memory allocations, you definitely want to pass allocators to everything which allocates memory. Using replaced versions of the global memory management facilities may help you but it is fairly constrained. If you just want to write a custom container and memory allocation isn't much of your concern you don't necessarily need to bother. In big systems which are running for extensive periods of time memory allocation is one of the many concerns, however.
Allocators are classes that define memory models to be used by Standard Library containers.
Every Standard Library container has its own default allocator, However the users of the container can provide their own allocators over the default.
This is for additional flexibility.
It ensures that users can provide their own allocator which provides an alternate form of memory management(eg: Memory Pools) apart from the regular heap.
If you want to produce a standard-compatible container then the answer is of course yes... allocators are described in the standard so they are required.
In my personal experience however allocators are not that useful... therefore if you are developing a container for a specific use to overcome some structural limitation of the standard containers then I'd suggest to forget about allocators unless you really see a reason for using them.
If instead you are developing a container just because you think you can do better than the standard vector then my guess is that you are wasting your time. I don't like the allocator idea design (dropping on the type something that shouldn't be there) but luckily enough they can be just ignored. The only annoyance with allocators when you don't need them (i.e. always) is probably some more confusion in error messages.. that however are a mess anyway.
Has anyone seen an allocator that calls mlock(2) to prevent an STL container's contents from being swapped to disk?
There is afaik only one tricky part to writing such an allocator, namely minimizing the number of mlocked pages by clustering allocations to be mlocked. Ergo, one should probably start by modifying some shared memory allocator?
If I wanted to implement this (which is difficult to imagine, because I find it hard to believe it's the right solution to any problem :^), I'd try to do it by using a boost::pool_allocator (which provides a standard library compatible Allocator from a pool) and then - I forget the details; think it'll involve the RequestedSize template argument to singleton_pool and a user_allocator ? - there will be some way of having that sit on top of a pool which requests bigger chunks of memory by the mechanism of your choice which in your case would be allocation of mlocked pages.
Looking at vector, I realized that I have never used the second argument when creating vectors.
std::vector<int> myInts; // this is what I usually do
std::vector<int, ???> myOtherInts; // but is there a second argument there?
Looking at the link above it says that it is for:
Allocator object to be used instead of constructing a new one.
or, as for this one:
Allocator: Type of the allocator object used to define the storage allocation model. By default, the allocator class template for type T is used, which defines the simplest memory allocation model and is value-independent.
I guess it has to do with something with memory management. However, I am not sure how to use that.
Any pointers regarding this?
The default allocator, std::allocator<>, will handle all allocations made by std::vector<> (and others). It will make new allocations from the heap each time a new allocation is needed.
By providing a custom allocator, you can for instance allocate a big chunk of memory up front and then slice it up and hand out smaller pieces when separate allocations are needed. This will increase the allocation speed dramatically, which is good for example in games, at the cost of increased complexity as compared to the default allocator.
Some std type implementations have internal stack-based storage for small amounts of data. For instance, std::basic_string<> might use what is called a small string optimization, where only strings longer than some fixed length, say 16 characters (just an example!), gets an allocation from the allocator, otherwise an internal array is used.
Custom allocators are rarely used in general case. Some examples of where they can be useful:
Optimization for a specific pattern of allocations. For example, a concurrent program can pre-allocate a large chunk of memory via standard means at the beginning of task execution and then shave off pieces off it without blocking on the global heap mutex. When task is completed, entire memory block can be disposed of. To use this technique with STL containers, a custom allocator can be employed.
Embedded software, where a device has several ranges of memory with different properties (cached/noncached, fast/slow, volatile/persistent etc). A custom allocator can be used to place objects stored in an STL container in a specific memory region.
Maybe this will help: http://www.codeguru.com/cpp/cpp/cpp_mfc/stl/article.php/c4079
You may try google for: stl allocator.
Allocators (STL) help you to manage memory for your objects in vector class. you may use the custom allocator for different memory model( etc).
Hi you can find example of custom allocator http://www.codeproject.com/KB/cpp/allocator.aspx