Standard library container that doesn't require object reallocation / move operations? - c++

I built a C++ wrapper around the FreeRTOS timer API. My class statically allocates the timer control block which is operated by a FreeRTOS thread in the background. This means that if I move or copy this object, the control block will be moved/copied as well BUT the thread wont notice that. Because of that I consider the object non-copyable and non-movable.
Here's the outline:
#include <cstdint>
#include <concepts>
template <std::invocable Cb>
class timer
{
public:
timer() = default;
timer(Cb cb, TickType_t timer_period, bool auto_reload = false)
: cb_{ cb }
{
xTimerCreateStatic("timer", timer_period, auto_reload, static_cast<void*>(this), &timer::timer_expired_cb, &buf_);
}
timer(const timer&) = delete;
timer(timer&&) = delete;
auto operator=(const timer&) = delete;
auto operator=(timer&&) = delete;
// ...
private:
Cb cb_;
TimerHandle_t handle_;
StaticTimer_t buf_;
};
Now I want to push multiple of this timer objects into a C++ container which I can dynamically extend or shrink as objects enter or leave the container. Is there a stdlib container that doesn't require objects to be moveable or copyable and still provides all the functionality?

I see four basic options:
std::list<timer>: This might be one of the very rare cases when using std::list is the best option. Insertion into the list must be done via one of the emplace member functions, as you cannot move in an already existing object.
std::vector<std::unique_ptr<timer>>: In case construction of timer objects is not directly associated with keeping them in your container. This has the disadvantage that accessing and removing entries slightly more work than std::list. But your timer factory doesn't need to know how you plan to store the object.
std::set<timer>: You stated that you have new objects arriving and departing. If you have a lot of them, maybe you want to avoid finding them in a linear container. std::set also has no reallocations and offers you a nice interface for finding and erasing objects. But clearly it has more overhead than the other two suggestions.
std::array<std::optional<timer>, N>: If you know the maximal number N of timers you will see at runtime, consider a fixed-size array with optionals in it. This has no pointer-indirections but you likely have a number of branches when searching an item.

Related

Keeping track of (stack-allocated) objects

In a rather large application, I want to keep track of some statistics about objects of a certain class. In order to not degrade performance, I want the stats to be updated in a pull-configuration. Hence, I need to have a reference to each live object in some location. Is there an idiomatic way to:
Create, search, iterate such references
Manage it automatically (i.e. remove the reference upon destruction)
I am thinking in terms of a set of smart pointers here, but the memory management would be somewhat inverted: Instead of destroying the object when the smart pointer is destroyed, I'd want the smart pointer to be removed, when the object is destroyed. Ideally, I do not want to reinvent the wheel.
I could live with a delay in the removal of the pointers, I'd just need a way to invalidate them quickly.
edit: Because paddy asked for it: The reason for pull-based collection is that obtaining the information may be relatively costly. Pushing is obviously a clean solution but considered too expensive.
There is no special feature of the language that will allow you to do this. Sometimes object tracking is handled by rolling your own memory allocator, but this doesn't work easily on the stack.
But if you're using only the stack it actually makes your problem easier, assuming that the objects being tracked are on a single thread. C++ makes special guarantees about the order of construction and destruction on the stack. That is, the destruction order is exactly the reverse of construction order.
And so, you can leverage this to store a single pointer in each object, plus one static pointer to track the most recent one. Now you have an object stack represented as a linked list.
template <typename T>
class Trackable
{
public:
Trackable()
: previous( current() )
{
current() = this;
}
~Trackable()
{
current() = previous;
}
// External interface
static const T *head() const { return dynamic_cast<const T*>( current() ); }
const T *next() const { return dynamic_cast<const T*>( previous ); }
private:
static Trackable * & current()
{
static Trackable *ptr = nullptr;
return ptr;
}
Trackable *previous;
}
Example:
struct Foo : Trackable<Foo> {};
struct Bar : Trackable<Bar> {};
// :::
// Walk linked list of Foo objects currently on stack.
for( Foo *foo = Foo::head(); foo; foo = foo->next() )
{
// Do kung foo
}
Now, admittedly this is a very simplistic solution. In a large application you may have multiple stacks using your objects. You could handle stacks on multiple threads by making current() use thread_local semantics. Although you need some magic to make this work, as head() would need to point at a registry of threads, and that would require synchronization.
You definitely don't want to synchronize all stacks into a single list, because that will kill your program's performance scalability.
As for your pull-requirement, I presume it's a separate thread wanting to walk over the list. You would need a way to synchronize such that all new object construction or destruction is blocked inside Trackable<T> while the list is being iterated. Or similar.
But at least you could take this basic idea and extend it to your needs.
Remember, you can't use this simple list approach if you allocate your objects dynamically. For that you would need a bi-directional list.
The simplest approach is to have code inside each object so that it registers itself on instantiation and removes itself upon destruction. This code can easily be injected using a CRTP:
template <class T>
struct AutoRef {
static auto &all() {
static std::set<T*> theSet;
return theSet;
}
private:
friend T;
AutoRef() { all().insert(static_cast<T*>(this)); }
~AutoRef() { all().erase(static_cast<T*>(this)); }
};
Now a Foo class can inherit from AutoRef<Foo> to have its instances referenced inside AutoRef<Foo>::all().
See it live on Coliru

Resize a std::vector<std::atomic_bool> assigning true to all atomic bools

I have a std::vector<std::atomic_bool> that I want to resize to some arbitrary n, wherein all newly created objects are assigned a value of true. The program will not build because resize() relies on the copy constructor of the data type, not its assignment operator. Is there any way to assign a default value to an atomic_bool or would I be stuck with using a loop and store()ing all the values?
What I've tried:
#include <atomic>
#include <vector>
class foo() {
public:
std::vector<std::atomic_bool> vec;
foo() {
std::atomic_bool temp(true);
vec.resize(100, std::atomic_bool(true)); //try 1
vec.resize(100, temp); //try 2
}
}
If T is neither copyable nor movable, then std::vector<T> cannot be resized. Period. In this case, you might want to consider std::deque.
std::deque<std::atomic_bool> D;
D.emplace_back(true); // write a helper to do this 100 times if you want
However, note that a standard library container of atomics is not atomic; adding new elements to the container is not an atomic operation so you will probably have to protect the container with a mutex, which might eliminate any benefits of storing atomics inside.
Brian's suggestion of a deque is sound and still allows O(1) random access, though I'd expect it to be a couple times slower than a vector. Kerrek's suggestion of a higher level class managing a vector's also workable.
FWIW, another option is wrapping the individual std::atomic_bools with a type that orchestrates copy construction as a combination of default construction and assignment:
struct Copy_Constructible_Atomic_Bool : std::atomic_bool
{
Copy_Constructible_Atomic_Bool(const std::atomic_bool& rhs)
{
std::atomic_bool::operator=(rhs);
}
Copy_Constructible_Atomic_Bool(const Copy_Constructible_Atomic_Bool& rhs)
{
std::atomic_bool::operator=(rhs);
}
};
Usage:
std::vector<Copy_Constructible_Atomic_Bool> vec;
std::atomic_bool temp;
temp = true;
vec.resize(100, temp);
atomics aren't designed to be moved, so you cant reallocate them to be somewhere else. However, you can replace them.
vec = std::vector<std::atomic_bool>(100, true);
(I'm not 100% certain you can use true here, but I believe you can.)

Parallel Command Pattern

I wanted to know of how to make my use of the command pattern thread-safe while maintaining performance. I have a simulation where I perform upwards of tens of billions of iterations; performance is critical.
In this simulation, I have a bunch of Moves that perform commands on objects in my simulation. The base class looks like this:
class Move
{
public:
virtual ~Move(){}
// Perform a move.
virtual void Perform(Object& obj) = 0;
// Undo a move.
virtual void Undo() = 0;
};
The reason I have the object passed in on Perform rather than the constructor, as is typical with the Command pattern, is that I cannot afford to instantiate a new Move object every iteration. Rather, a concrete implementation of Move would simply take Object, maintain a pointer to it and it's previous state for when it's needed. Here's an example of a concrete implementation:
class ConcreteMove : public Move
{
std::string _ns;
std::string _prev;
Object* _obj;
ConcreteMove(std::string newstring): _ns(newstring) {}
virtual void Perform(Object& obj) override
{
_obj= &obj;
_prev = obj.GetIdentifier();
obj.SetIdentifier(_ns);
}
virtual void Undo()
{
_obj->SetIdentifier(_prev);
}
};
Unfortunately, what this has cost me is thread-safety. I want to parallelize my loop, where multiple iterators perform moves on a bunch of objects simultaneously. But obviously one instance of ConcreteMove cannot be reused because of how I implemented it.
I considered having Perform return a State object which can be passed into Undo, that way making the implementation thread-safe, since it is independent of the ConcereteMove state. However, the creation and destruction of such an object on each iteration is too costly.
Furthermore, the simulation has a vector of Moves because multiple moves can be performed every iteration stored in a MoveManager class which contains a vector of Move object pointers instantiated by the client. I set it up this way because the constructors of each particular Concrete moves take parameters (see above example).
I considered writing a copy operator for Move and MoveManager such that it can be duplicated amongst the threads, but I don't believe that is a proper answer because then the ownership of the Move objects falls on MoveManager rather than the client (who is only responsible for the first instance). Also, the same would be said for MoveManager and responsibility of maintaining that.
Update: Here's my MoveManager if it matters
class MoveManager
{
private:
std::vector<Move*> _moves;
public:
void PushMove(Move& move)
{
_moves.push_back(&move);
}
void PopMove()
{
_moves.pop_back();
}
// Select a move by index.
Move* SelectMove(int i)
{
return _moves[i];
}
// Get the number of moves.
int GetMoveCount()
{
return (int)_moves.size();
}
};
Clarification: All I need is one collection of Move objects per thread. They are re-used every iteration, where Perform is called on different objects each time.
Does anyone know how to solve this problem efficiently in a thread-safe manner?
Thanks!
What about the notion of a thread ID. Also, why not preconstruct the identifier strings and pass pointers to them?
class ConcreteMove : public Move
{
std::string *_ns;
std::vector<std::string *> _prev;
std::vector<Object *> _obj;
ConcreteMove(unsigned numthreads, std::string *newstring)
: _ns(newstring),
_prev(numthreads),
_obj(numthreads)
{
}
virtual void Perform(unsigned threadid, Object &obj) override
{
_obj[threadid] = &obj;
_prev[threadid] = obj.GetIdentifier();
obj.SetIdentifier(_ns);
}
virtual void Undo(unsigned threadid)
{
_obj[threadid]->SetIdentifier(_prev[threadid]);
}
};
Impossible with stated requirements. Specifically,
Use the command pattern. "the command pattern is a behavioral design pattern in which an object is used to represent and encapsulate all the information needed to call a method at a later time." Thus you're storing data.
You "can't afford" to allocate memory.
You have "billions" of iterations, which means some large static allocation won't suffice.
You want to store data without any place to store it. Thus there is no answer. However, if you're willing to change your requirements, there are undoubtedly many ways to solve your problem (whatever it may be -- I couldn't tell from the description.)
I also can't estimate how many Move objects you need at once. If that number is reasonably low then a specialized allocation scheme might solve part of your problem. Likewise, if most of the Move objects are duplicates, a different specialized allocation scheme might help.
In general what you're asking can't be solved, but relax the requirements and it shouldn't be hard.
Your Move Manager should not contain a vector of pointers, it should be a vector of Move objects
std::vector<Move> _moves;
It seems you will have one Move Manager per thread, so no issue of multi-threading problems, set the vector capacity at max, and then apply perform and other actions on the move in the vector
No new allocation, and you will be reusing the move objects

SMART vector for RAW pointers in C++11?

I'm using an old open-source library, with the following (simplified) API of interest:
// some class that holds a raw pointer to memory on the heap
// DOES NOT delete it in its destructor
// DOES NOT do a "deep" copy when copied/assigned (i.e., after copying both objects
// will point to the same address)
class Point;
// function used to construct a point and allocate its data on the heap
Point AllocPoint();
// function used to release the memory of the point's data
void DeallocPoint(Point& p);
// Receives a pointer/c-array of Points, along with the number of points
// Doesn't own the memory
void Foo(Point* points, int npts);
What's the best (safest/most readable/most elegant) way of using this API in C++11. I can't simply use vector<unique_ptr<Point, PointDeleter>> (where PointDeleter is a simple custom deleter I can implement), because then I will not be able to use the function Foo (which expects Point* and not unique_ptr<Point>*).
Thanks
If you really want to make it look nice, you're probably going to have to write a set of really comprehensive wrappers which completely hide the library's API - effectively, wrap the entire library with one that behaves in a modern C++ way on the outside and hides all the mess inside.
Not a pleasant task, but if you can get the behaviour of that library right then it should make your life a lot easier in the long term. Might not be worth it if you're not going to use this external library very extensively though.
I would wrap this non-RAII C-like API in RAII building blocks, and then use them in C++11 code.
For example: you can define a RaiiPoint class that wraps the (non-RAII) Point class, and in its constructor calls AllocPoint(), in the destructor DeallocPoint(). Then you can define proper copy constructor and copy operator=, or just implement move semantics (with move constructor and move operator=), or make the wrapper class both copyable and movable, basing on your requirements.
Then you can simply use a std::vector<RaiiPoint> with your RAII-based wrapper class.
(This is a general approach that you can use when you want to use C libraries in modern C++ code: you can wrap the "raw" C library handles and objects in safe RAII boundaries, and use these robust safe wrapper classes in your modern C++ code.)
You can use std::vector<Point>, calling Foo( &v[0],
v.size() ). But managing the memory here could be tricky,
since Point apparently doesn't provide any clean copy and
assignment; a custom deleter in the allocator will be called for
each element, even if it is copied.
If the vector should actually own the points, then you can wrap
it in a more complex class, which calls AllocPoint for each
insertion (and inserts the results), and DeallocPoint for each
removal (and for everything remaining in the vector on
destruction). This class should not allow write access to the
Point (non-const operator[], non-const iterators, etc.),
however, since this would allow changing any pointers in
Point, and loosing what is needed for DeallocPoint to work
correctly. Presumably, there other functions for manipulating
Point; you'll have to arrange for these to be available
through the wrapper interface.
"You" could write a simple wrapper to free the memory:
struct PointVectorWrapper {
vector<Point> points;
~PointVectorWrapper() {
for (Point& p : points) {
DeallocPoint(p);
}
}
PointVectorWrapper& operator=(const PointVectorWrapper&) = delete;
PointVectorWrapper(const PointVectorWrapper&) = delete;
};
// Now the usage is simple and safe:
PointVectorWrapper points;
// ... populate points ...
Foo(points.data(), points.size())
But this seems a little "adhoc". What's a more standard/reusable solution?
You could use a standard vector with a custom allocator, that invoke AllocPoint on construct method and DeallocPoint() on destruct method.
template<typename T>
class CustomAllocator : public std::allocator<T>
{
//Rebind and constructors
};
template<>
class CustomAllocator<Point> : public std::allocator<Point>
{
//Rebind and constructors
//For c++11
void construct( pointer p )
{
new (p) Point();
*p = AllocPoint();
}
void construct( pointer p, const_reference val )
{
construct(p);
//copy member from val to point if neccessary
};
void destroy( pointer p )
{
DeallocPoint(*p);
p->~Point();
}
};
typedef std::vector<Point, CustomAllocator<Point> > PointVector;

transferring object ownership on std::allocator rebind

I have a Visual Studio 2008 C++ application where I am implementing a replacement for the standard allocator used in containers like std::vector. But, I've run in to an issue. My implementation relies on the allocator owning a handle to a resource. In the case where the rebind feature is used, I would need to transfer ownership of the handle to the new allocator. Something like this:
template< class T >
class MyAllocator
{
public:
template< class U >
explicit MyAllocator( const MyAllocator< U >& other ) throw()
: h_( other.Detach() ) // can't do this to a `const`
{
};
// ...
private:
HANDLE Detach()
{
HANDLE h = h_;
h_ = NULL;
return h;
};
HANDLE h_;
}; // class MyAllocator
Unfortunately, I can't relieve the old allocator of the handle ownership because it is const. If I remove const from the rebind constructor, then the containers won't accept it.
error C2558: class 'MyAllocator<T>' : no copy constructor available or copy constructor is declared 'explicit'
Is there a good way around this issue?
Without really knowing much about allocators (never needed them): Your copy ctor takes a const ref, thus promising to not to change the other object, but you attempt to change it anyway. Although there's cases where classes were designed that way (std::auto_ptr), this does seem fishy.
Syntactically, you could always declare h_ mutable, and make Detach() a const member function, but I'd seriously question the semantics of this setup, before hacking my way through the syntactic jungle using a broadsword.
What happens if you declare h_ as mutable?
You can solve this with an extra level of indirection but it's not an ideal solution. Basically, your allocator would have a pointer to a handle which would be allocated/deallocated in the constructor/destructor. The handle that it points to would be non-const throughout, so you can "move" the handle from one allocator to another. This does add some overhead to the allocator though.
I don't know your exact case but it seems that a stateful allocator that's non-trivially copyable should be carefully considered for all its implications. Is there an alternate way you can simplify its design so it doesn't have a move-only handle?
You can't transfer the ownership, because the allocator may be copied and rebound multiple times even in a single container and the resulting instances used simultaneously.
You'll have to share the resource instead. Create an indirection for the resource with reference-count. Something like:
class SharedHandle {
HANDLE h_;
int count;
SharedHandle(HANDLE h) : h_(h), count(1) {}
~SharedHandle() { CloseHandle(h_); } // or whatever to release the resource.
SharedHandle *Ref() { ++count; return this; }
void Unref() { if(!--count) delete this; }
}
and than:
explicit MyAllocator( const MyAllocator< U >& other ) throw()
: h_( other.h_->Ref() )
In addition to containers that naturally need to allocate heterogenous blocks like hash_map/unordered_map, Microsoft implementation of containers is known to allocate various strange things. When I traced allocations in one Windows application, there were many allocations of strange sizes comming from somewhere inside STL.