C++ allocators_trait::construct: motivation, trade-offs in ignoring - c++

I'm wrestling with some pain being caused by std::allocator_traits::construct. In order for a container to be a "conforming" user of the allocator concept, it needs to use construct rather than placement new to construct objects. This is very sticky for me. Currently I have a class (class A) that is designed to be allocator aware, and at some point it needs to create another instance of some other class (class B) in allocated memory. The problem is that class B implements the construction of the new object. If I could use placement new, this wouldn't be an issue: A would handle allocation, pass B the memory address, and B would construct into that. But since the construction needs to be performed via construct, I need to inject the allocator type into B, templating it, which creates a huge mess.
It's bad enough that I am seriously considering just using placement new, and static asserting that my instance of the allocator does not have a construct method (note that the static construct function calls the instance method if it exists, otherwise it calls placement new). I have never felt the tiniest urge to write a construct method for an allocator. The cost of making this part of the allocator concept seems very high to me; construction has gotten entangled with allocation, where allocators were supposed to help separate them. What justifies the existence of construct/destruct? Insight into the design decision, examples of real (not toy) use cases, or thoughts on the gravity of electing to simply use placement new appreciated.
There is a similar question; std::allocator construct/destroy vs. placement new/p->~T(). It was asked quite a long time ago, and I don't find the answer accepted there as sufficient. Logging is a bit trite as a use case, and even then: why is the allocator logging the actual construction of objects? It can log allocations and deallocations in allocate and deallocate, it doesn't answer the question in the sense of: why was construction made a province of the allocator in the first place? I'm hoping to find a better answer; it's been quite a few years and much about allocators has changed since then (e.g. allocators being stateful since 11).

A few points:
There really isn't a std container concept. The container requirements tables in the standard are there to document the containers specified by the standard.
If you have a container that wants to interact with std::allocator_traits<Alloc>, all you have to do is assume that Alloc conforms to the minimum C++11 allocator requirements and interact with it via std::allocator_traits<Alloc>.
You are not required to call std::allocator_traits<Alloc>::construct.
You are forbidden from calling Alloc::construct because it may not exist.
The standard-specified containers are required to call std::allocator_traits<Alloc>::construct only for container::value_type, and are forbidden from using std::allocator_traits<Alloc>::construct on any other types the container may need to construct (e.g. internal nodes).
Why was construct included in the "allocator concept" way back in C++98?
Probably because the committee at the time felt that this would ease dealing with x86 near and far pointers -- a problem that no longer exists today.
That being said, std::scoped_allocator_adaptor is a modern real-world example of an allocator that customizes both construct and destroy. For the detailed specification of those customizations I point you towards the latest C++1z working draft, N4567. The spec is not simple, and that is why I'm not attempting to reproduce it here.

Related

What is the purpose and usage of `memory_resource`?

The standard C++17 include a new namespace pmr including a set of classes grouped under the name of memory_resource.
After a search on internet, I found very few vulgarized information about it, the direct consequence is this question:
What are the main ideas behind pmr and especially pmr::memory_resource?
Detailing a bit more the question, some of the question marks in my head are:
What does it bring new, or what were the limitations it solve?
What is the difference with allocator?
Does polymorphic mean it is possible to select runtime the allocator provided to a container constructor? (e.g. for testing purpose)
Does it helps for implementing memory pool, or other memory management schemes?
Context:
In the intend of creating a memory pool allocator, I found information about this namespace. Reading names like pool_options or polymorphic_allocator raised my attention.
Related questions:
polymorphic_allocator: when and why should I use it?
A polymorphic_allocator is intended to let you have an allocator whose behavior is dynamically determined at runtime.
The only way to create a polymorphic_allocator is:
Default constructed, in which case it uses std::pmr::get_default_resource() return value, which is a memory_resource*.
Pass it a memory_resource*.
copy from another polymorphic_allocator.
So the point of customization for a polymorphic_allocator is creating a class that inherits from memory_resource and implementing its methods, or using one of the pre-declared memory_resources that are defined in std::pmr: (un)synchronized_pool_resource and monotonic_buffer_resource as types, or std::pmr::new_delete_resource() / std::pmr::null_memory_resource().
Suppose you want a your memory to be allocated using a strategy different than the 5 provided in std::pmr. Then you make a class that inherits from std::pmr::memory_resource, and pass it to a container which uses a polymorphic_allocator.

std::string with no free store memory allocation

I have a question very similar to
How do I allocate a std::string on the stack using glibc's string implementation?
but I think it's worth asking again.
I want an std::string with local storage that overflows into the free store. std::basic_string provides an allocator as a template parameter, so it seems like the thing to do is to write an allocator with local storage and use it to parameterize the basic_string, like so:
std::basic_string<
char,
std::char_traits<char>,
inline_allocator<char, 10>
>
x("test");
I tried to write the inline_allocator class that would work the way you'd expect: it reserves 10 bytes for storage, and if the basic_string needs more than 10 bytes, then it calls ::operator new(). I couldn't get it to work. In the course of executing the above line of code, my GCC 4.5 standard string library calls the copy constructor for inline_allocator 4 times. It's not clear to me that there's a sensible way to write the copy constructor for inline_allocator.
In the other StackOverflow thread, Eric Melski provided this link to a class in Chromium:
http://src.chromium.org/svn/trunk/src/base/stack_container.h
which is interesting, but it's not a drop-in replacement for std::string, because it wraps the std::basic_string in a container so that you have to call an overloaded operator->() to get at the std::basic_string.
I can't find any other solutions to this problem. Could it be that there is no good solution? And if that's true, then are the std::basic_string and std::allocator concepts badly flawed? I mean, it seems like this should be a very basic and simple use case for std::basic_string and std::allocator. I suppose the std::allocator concept is designed primarily for pools, but I think it ought to cover this as well.
It seems like the rvalue-reference move semantics in C++0x might make it possible to write inline_allocator, if the string library is re-written so that basic_string uses the move constructor of its allocator instead of the copy constructor. Does anyone know what the prospect is for that outcome?
My application needs to construct a million tiny ASCII strings per second, so I ended up writing my own fixed-length string class based on Boost.Array, which works fine, but this is still bothering me.
Andrei Alexandrescu, C++ programmer extraordinaire who wrote "Modern C++ Design" once wrote a great article about building different string implementations with customizable storage systems. His article (linked here) describes how you can do what you've described above as a special case of a much more general system that can handle all sorts of clever memory allocation requirements. This doesn't talk so much about std::string and focuses more on a completely customized string class, but you might want to look into it as there are some real gems in the implementation.
C++2011 is really going to help you here :)
The fact is that the allocator concept in C++03 was crippled. One of the requirement was that an allocator of type A should be able to deallocate memory from any other allocator from type A... Unfortunately this requirement is also at odds with stateful allocators each hooked to its own pool.
Howard Hinnant (who manages the STL subgroup of the C++ commitee and is implementing a new STL from scratch for C++0x) has explored stack-based allocators on his website, which you could get inspiration from.
This is generally unnecessary. It's called the "short string optimization", and most implementations of std::string already include it. It may be hard to find, but it's usually there anyway.
Just for example, here's the relevant piece of sso_string_base.h that's part of MinGW:
enum { _S_local_capacity = 15 };
union
{
_CharT _M_local_data[_S_local_capacity + 1];
size_type _M_allocated_capacity;
};
The _M_local_data member is the relevant one -- space for it to store (up to) 15 characters (plus a NUL terminator) without allocating any space on the heap.
If memory serves, the Dinkumware library included with VC++ allocates space for 20 characters, though it's been a while since I looked, so I can't swear to that (and tracking down much of anything in their headers tends to be a pain, so I prefer to avoid looking if I can).
In any case, I'd give good odds that you've been engaged in that all-too-popular pass-time known as premature optimization.
I believe the code from Chromium just wraps things into a nice shell. But you can get the same effect without using the Chromium wrapper container.
Because the allocator object gets copied so often, it needs to hold a reference or pointer to the memory. So what you'd need to do is create the storage buffer, create the allocator object, then call the std::string constructor with the allocator.
It will be a lot wordier than using the wrapper class but should get the same effect.
You can see an example of the verbose method (still using the chromium stuff) in my question about stack vectors.

worst that can happen if i don't obey the stateless custom allocators dogma?

I need to create a custom allocator for std:: objects (particularly and initially for std::vector) but it might eventually come to use others
The reason I need to create a custom allocator is that I need to track allocated (heap & stack) resources by individual components of the application (this is an inherent feature of the application). I will need the custom allocator to monitor the heap portion of the resources, so it is essential that I'm able to pass to the std::vector constructor something like
trackerId idToTrackUsage;
myAlloca<int> allocator(idToTrackUsage);
vector<int> Foo( allocator );
However, after reading a bit I found this little bomb about the STL / C++ standard (see references) saying that all allocator instances of a given type should be equivalent (that is that == should return true for any two instances) and, most terminal; any allocator should be able to deallocate memory allocated by any other instance (that is, without having a way to know what that other instance might be). In short, allocators cannot have state.
So I'm trying to find the best way around this. Any clever ideas? I really really REALLY don't want to have to keep a custom version of std::vector around.
EDIT: i read about scoped allocators for c++0x on http://www2.research.att.com/~bs/C++0xFAQ.html#scoped-allocator but i couldn't really get far into understanding how this applies to my problem. If anyone thinks c++0x alleviates this problem, please comment
References:
Allocator C++ article in Wikipedia
Some random further reading courtesy of Google
Aside from the obvious answer ("if you violate any requirement, that's undefined behavior, good night and thanks for playing"), I imagine the worst that would likely happen, is that the vector implementation can rely on the requirement that "all instances of the allocator class are interchangeable" in the obvious way:
vector(const Allocator &youralloc = Allocator()) {
const Allocator hawhaw;
// use hawhaw and ignore youralloc.
// They're interchangeable, remember?
}
Looking at the source, GCC's vector implementation (which I think is based eventually on SGI's original STL implementation) does sort-of store a copy of the allocator object passed into that constructor, so there's some hope that this won't happen.
I'd say try it and see, and document what you've done very carefully, so that anyone attempting to use your code on an implementation that you haven't checked, knows what's going on. Implementers are encouraged in the standard to relax the restrictions on allocators, so it would be a dirty trick to make it look as though they're relaxed when really they aren't. Which doesn't mean it won't happen.
If you're really lucky, there's some documentation for your container implementation that talks about allocators.
You could, of course, leave a pointer to whatever state you need in any allocated blocks. This does of course mean that any per-block state must be stored in that block, and the allocator instances would act more like handles than actual objects in as of themselves.
Making the allocator state static would do the trick, if you're able to work with that. It does mean that all allocators of that type will have to share their state, but from your requirements, that sounds like it could be acceptable
To respond to your edit: yes, in C++0x or C++11, allocators can have state.

Creating a scoped custom memory pool/allocator?

Would it be possible in C++ to create a custom allocator that works simply like this:
{
// Limit memory to 1024 KB
ScopedMemoryPool memoryPool(1024 * 1024);
// From here on all heap allocations ('new', 'malloc', ...) take memory from the pool.
// If the pool is depleted these calls result in an exception being thrown.
// Examples:
std::vector<int> integers(10);
int a * = new int [10];
}
I couldn't find something like this in the boost libraries, or anywhere else.
Is there a fundamental problem that makes this impossible?
You would need to create a custom allocator that you pass in as a template param to vector. This custom allocator would essentially wrap the access to your pool and do whatever size validations that it wants.
Yes you can make such a construct, it's used in many games, but you'll basically need to implement your own containers and call memory allocation methods of that pool that you've created.
You could also experiment with writing a custom allocator for the STL containers, although it seems that that sort of work is generally advised against. (I've done it before and it was tedious, but I don't remember any specific problems.)
Mind- writing your own memory allocator is not for the faint of heart. You could take a look at Doug Lea's malloc, which provides "memory spaces", which you could use in your scoping construct somehow.
I will answer a different question. Look at 'efficient c++' book. One of the things they discuss is implementing this kind of thing. That was for a web server
For this particular thing you can either mess at the c++ layer by overriding new and supplying custom allocators to the STL.
Or you can mess at the malloc level, start with a custom malloc and work from there (like dmalloc)
Is there a fundamental problem that makes this impossible?
Arguing about program behavior would become fundamentally impossible. All sorts of weird issues will come up. Certain sections of the code may or may not execute though this will seeminly have no effect on the next sections which may work un-hindered. Certain sections may always fail. Dealing with the standard-library or any other third party library will become extremely difficult. There may be fragmentations at run-time at times and at times not.
If intent is that all allocations within that scope occur with that allocator object, then it's essentially a thread-local variable.
So, there will be multithreading issues if you use a static or global variable to implement it. Otherwise, not a bad workaround for the statelessness of allocators.
(Of course, you'll need to pass a second template argument eg vector< int, UseScopedPool >.)

Understanding the library functions in c++ [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 13 years ago.
If I'd like to know how a function written in like standard C++ library work (not just the MSDN description). I mean how does it allocate, manage, deallocate memory and return you the result. where or what do you need to know to understand that?
You can look at the library headers. A lot of functionality is actually implemented there because the library is highly templatized (and templates generally need to be implemented in headers). The location of the headers depends on the compiler, but you should be able to find them quite easily (e.g. search for a file named algorithm).
You may also ask the compiler to preprocess your code to see all the related headers (this will produce extremely long output). With GCC you can do this by g++ -E yoursource.cc.
If what you are looking for isn't implemented in headers, you need the library sources, which are generally not installed by default and which are not even available for commercial compilers such as MSVC. Look for glibc (C library) and libstdc++ (C++ library), which are the ones used by GCC and some other compilers.
In any case, notice that the standard library implementations tend to be rather cryptic due to a lot of underscores being used in variable names and such (to avoid name collisions with user's macros), and often they are also infested with #ifdefs and other preprocessor cruft.
You need to know the techniques used to write C++ libraries. Getting Bjarne Stroustrup's book is a good start. Also, SGI has very detailed documentation on the STL at a suitably high level of abstraction.
If you are going to be investigating the windows based stuff you might want to study the systems part of the windows library.
To complement windows: understanding the Posix specification is also important.
First a few basic data-structure principles, then a note and some links about allocators...
The STL containers use a number of different data structures. The map, set, multimap and multiset are normally implemented as binary trees with red-black balancing rules, for example, and deque is possibly (more impression than knowledge) a circular queue in an array, exploiting an array-doubling or similar growth pattern.
None of the data structures are actually defined by the standard - but the specified performance characteristics limit the choices significantly.
Normally, your contained data is contained directly in the data structure nodes, which are held (by default) in heap allocated memory. You can override the source of memory for nodes by providing an allocator template parameter when you specify the container - more on that later. If you need the container nodes to reference (not contain) your items, specify a pointer or smart-pointer type as the contained type.
For example, in an std::set, the nodes will be binary tree nodes with space in them for an int and the two child pointers, and the metadata that the library needs (e.g. the red/black flag). The binary tree node will not move around your applications address-space, so you can store pointers to your data item elsewhere if you want, but that isn't true for all containers - e.g. an insert in a vector moves all items above the insert point up by one, and may have to reallocate the whole vector, moving all items.
The container class instance is normally very small - a few pointers is typical. For example, the std::set etc usually have a root pointer, a pointer to the lowest-key node and a pointer to the highest-key node, and probably a bit more metadata.
One issue the STL faces is creating and destroying instances in multi-item nodes without creating/destroying the node. This happens in std::vector and std::deque, for instance. I don't know, strictly, how the STL does it - but the obvious approach requires placement new and explicit destructor calls.
Placement new allows you to create an object in an already-allocated piece of memory. It basically calls the constructor for you. It can take parameters, so it can call a copy constructor or other constructor, not just the default constructor.
http://www.devx.com/tips/Tip/12582
To destruct, you literally call the destructor explicitly, via a (correctly typed) pointer.
((mytype*) (void*) x)->~mytype ();
This works if you haven't declared an explicit constructor, and even for built-in types like "int" that don't need destructing.
Likewise, to assign from one constructed instance to another, you make an explicit call to operator=.
Basically, the containers are able to create, copy and destroy data within an existing node fairly easily, and where needed, metadata tracks which items are currently constructed in the node - e.g. size() indicates which items are currently constructed in an std::vector - there may be additional non-constructed items, depending on the current capacity().
EDIT - It's possible that the STL can optimise by using (directly, or in effect) std::swap rather than operator= to move data around. This would be good where the data items are (for example) other STL containers, and thus own lots of referenced data - swapping could avoid lots of copying. I don't know if the standard requires this, or allows but doesn't mandate it. There is a well-known mechanism for doing this kind of thing, though, using a "traits" template. The default "traits" can provide an assignment-using method whereas specific overrides may support special-case types by using a swapping method. The abstraction would be a move where you don't care what is left in the source (original data, data from target, whatever) as long as it's valid and destructible.
In binary tree nodes, of course, there should be no need for this as there is only one item per node and it's always constructed.
The remaining problem is how to reserve correctly-aligned and correctly-sized space within a node struct to hold an unknown type (specified as a template parameter) without getting unwanted constructor/destructor calls when you create/destroy the node. This will get easier in C++0x, since a union will be able to hold non-POD types, giving a convenient uninitialised-space type. Until then, there's a range of tricks that more-or-less work with different degrees of portability, and no doubt a good STL implementation is a good example to learn from.
Personally, my containers use a space-for-type template class. It uses compiler-specific allocation checks to determine the alignment at compile-time and some template trickery to choose from an array-of-chars, array-of-shorts, array-of-longs etc of the correct size. The non-portable alignment-checking tricks are selected using "#if defined" etc, and the template will fail (at compile time) when someone throws a 128-bit alignment requirement at it because I haven't allowed for that yet.
How to actually allocate the nodes? Well, most (all?) STL containers take an "Allocator" parameter, which is defaulted to "allocator". That standard implementation gets memory from and releases it to the heap. Implement the right interface and it can be replaced with a custom allocator.
Doing that is something I don't like to do, and certainly not without Stroustrups "The C++ Programming Language" on my desk. There's a lot of requirements to meet in your allocator class, and at least in the past (things may have improved), compiler error messages were not helpful.
Google says you could look here, though...
http://www2.roguewave.com/support/docs/leif/sourcepro/html/toolsug/12-6.html
http://en.wikipedia.org/wiki/Allocator_%28C%2B%2B%29
Operating system functions to allocate/free memory are not really relevant to the C++ standard library.
The standard library containers will (by default) use new and delete for memory, and that uses a compiler-specific runtime which almost certainly manages its own heap data structure. This approach is generally more appropriate for typical applications use, where the platform-specific operating system heap is usually more appropriate for allocating large blocks.
The application heap will allocate/free memory from the operating system heap, but "how?" and "when?" are platform-specific and compiler-specific details.
For the Win32 memory management APIs, look here...
http://msdn.microsoft.com/en-us/library/ms810603.aspx
I'm sure you can find win64 equivalents if needed.
I haven't this book, but according to its description, http://www.amazon.com/C-Standard-Template-Library/dp/0134376331 includes
-Practical techniques for using and implementing the component
Isn't this what you want?