There is no particular language feature that allows you to do this. Sometimes object tracking is handled by moving your own memory allocator, but it doesn't work as easily on the stack.
But if you use only the stack, it actually simplifies your problem by assuming that the objects being tracked are on the same thread . C ++ gives special guarantees about the order of construction and destruction on the stack. That is, the order of destruction exactly corresponds to the order of construction.
So you can use this to store one pointer in each object, as well as one static pointer to keep track of the very last. Now you have a stack of objects presented as a linked list.
template <typename T> class Trackable { public: Trackable() : previous( current() ) { current() = this; } ~Trackable() { current() = 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 simplified solution. In a large application, you may have several stacks using your objects. You can process stacks across multiple threads by making current()
use thread_local semantics. Although you need magic to make this work, because head()
will need to point to the thread registry, and this will require synchronization.
You definitely do not want to synchronize all the stacks into one list, because it will kill the scalability of your program.
As for your traction requirement, I assume this is a separate thread that wants to go through the list. You will need a synchronization method such that the entire structure or destruction of a new object is locked inside Trackable<T>
while the list repeats. Or similar.
But at least you could take this basic idea and expand it to your needs.
Remember that you cannot use this simple approach if you dynamically select your objects. To do this, you will need a bidirectional list.