c++ Reliable way to remove all entries with UUID as the key - c++

So I have a bunch of std::unordered_maps that all have a common key but different datatypes for the data. I basically made a structure similar to a component based entity system, with the key being a entity class that contains a boost::uuid.
The adding works well but I am struggling with removing entire entities from the program. I can't find a reliable way to delete them without impairing running systems (I don't want to allow a delete in the middle of a frame to avoid one frame being glitched due to values being desynced or replaced with some default values) or that's terribly slow.
Right now I have a bool in the entity class and every frame the program goes through EVERY entity and checking if its set to true or not. IF yes the datapoint is removed from the map.
However I am not satisfied with it.
This is what the average entity looks like:
class Entity{
private:
boost::uuids::uuid uuid;
bool protect = false;
bool status = ENTITY_ALIVE;
public:
Entity()
:uuid(boost::uuids::random_generator()()){
}
const boost::uuids::uuid &operator ()()const{
return this->uuid;
}
bool operator ==(const Entity &othr)const{
return this->uuid==othr.uuid;
}
void copyComponents(const Entity &source,ComponentBase** mgrs, int c){
std::cout<<"copying...\n";
for(int i = 0; i < c; i ++){
std::cout<<"-";
mgrs[i]->copyTo(source,*this);
}
}
void kill(){
if(this->protect==false){
this->status = ENTITY_DEAD;
}
}
bool getStatus()const{
return this->status;
}
void setProtection(bool status){
this->protect = status;
}
bool getProtection(){
return this->protect;
}
~Entity(){
// std::cout<<"ENTITY WAS DELETED!!!!!!!!!!!"<<"\n";
}
};
struct EntityHasher{
size_t operator()(const Entity& obj)const{
return boost::uuids::hash_value((obj)());
}
};
Ok and this is what the maps look like:
typedef typename std::unordered_map<std::reference_wrapper<const Entity>,List<std::shared_ptr<t>>,EntityHasher,std::equal_to<const Entity>> mapType;
The list is a custom class I made that simply stores things in a doubly linked list. Nothing to worry about. I made this since accessing data was easier than using unordered_multi map.
What I have tried:
I have tried to store links to the classes containing the maps and simply directly having them delete it without much success.
I have tried to have is so when a "dead" entity is accessed its being added to a vector in the class storing the unordered map and then later cleared in a separate function called "removeCorpses". However that lead to lesser used components being left on for way too long and it was generally just really unstable (maybe I made a mistake implementing it)
Please suggest some good ways of going about deleting a Entity in all maps having it as a key without messing with the active frame etc.

You can use Boost.MultiIndex to construct a map-like structure that keeps corpses arranged first in a secondary sequenced index so that they can be erased when appropriate:
Live On Coliru
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index/member.hpp>
template<typename Key,typename Value>
struct delayed_erasure_unordered_map_value
{
Key first;
mutable Value second;
};
template<typename Key,typename Value>
using delayed_erasure_unordered_map_base=boost::multi_index_container<
delayed_erasure_unordered_map_value<Key,Value>,
boost::multi_index::indexed_by<
boost::multi_index::hashed_unique<
boost::multi_index::member<
delayed_erasure_unordered_map_value<Key,Value>,
Key,
&delayed_erasure_unordered_map_value<Key,Value>::first
>
>,
boost::multi_index::sequenced<>
>
>;
template<typename Key,typename Value>
class delayed_erasure_unordered_map:
public delayed_erasure_unordered_map_base<Key,Value>
{
using base=delayed_erasure_unordered_map_base<Key,Value>;
public:
using iterator=typename base::iterator;
using base::base;
void mark_for_erasure(iterator it) // marking same element twice is UB
{
auto pit=this->template project<1>(it);
auto& index=this->template get<1>();
index.relocate(index.begin(),pit);
++num_corpses;
}
void erase_marked()
{
auto& index=this->template get<1>();
for(;num_corpses;--num_corpses)index.erase(index.begin());
}
private:
std::size_t num_corpses=0;
};
#include <iostream>
int main()
{
delayed_erasure_unordered_map<int,int> m=
{{0,0},{1,1},{2,2},{3,3},{4,4},{5,5},{6,6},{7,7},{8,8},{9,9}};
for(auto it=m.begin(),end=m.end();it!=end;++it){
if(it->first%2)m.mark_for_erasure(it);
}
m.erase_marked();
for(const auto& x:m){
std::cout<<"{"<<x.first<<","<<x.second<<"} ";
}
}
Output
{0,0} {2,2} {4,4} {6,6} {8,8}

Related

map<Key,pair<A,B>> to map<Key,A>

I have a class that for some reasons needs to store a pair (say int,double) for each key, but whose interface only makes public one of the two values of the pair (int). One implementation may be
using namespace std;
class Foo {
public:
map<string,int> const & get() const {return external;}
void doStuff(string const & str) {
external.at(str);
internal.at(str);
}
private:
map<string,int> external;
map<string,double> internal;
};
The drawback is that doStuff has double lookup.
Another way is to store map<string,pair<int,double>> allin but then the accessor returning the whole map requires a copy.
The last way, of course, is to make the accessor more atomic by accessing a single key with a return allin.at(key).first;, which seems the best way but it breaks the interface I would like to provide.
I wonder, is there a way to avoid the double lookup in the "external/internal" version?
Another way could be to define a map entry with a private and a public value. Via a friend declaration the private value can be made visable to Foo class.
#include <iostream>
#include <string>
#include <map>
class Foo;
template<typename T1, typename T2>
struct my_map_entry
{
public:
my_map_entry()=default;
my_map_entry(T1 v, T2 pv)
{
value = v;
private_value = pv;
}
T1 value;
private:
T2 private_value;
friend class Foo;
};
class Foo {
public:
Foo(){
map["test"]=my_map_entry<int, double>(1, 2.0);
}
void doStuff(const std::string& str
{
auto entry = map.at(str);
std::cout<<"private_value: "<<entry.private_value<<std::endl;
}
std::map<std::string,my_map_entry<int, double>> map;
};
int main()
{
Foo test;
test.doStuff("test");
}
Given you just want the user to be able to retrieve the item, your get() method can be rewritten bearing that requirement in mind.
using namespace std;
class Foo {
public:
int *const get(string const &str) const {
auto it = map_.find(str)
return it == map_.end() ? nullptr : &it->first;
}
void doStuff(string const & str) {
map_.at(str);
}
private:
map<string,pair<int, double>> map_;
};
The idea is to return nullptr if the key was not found, or a pointer to the value if the key was found.
If instead you also want to be able to enumerate all the available ints, then you only have three choices:
Make your Foo class a map-like class, with its own iterators that wrap the ones from the inner map.
Use one of the available libraries to provide a view that helps you achieving the previous goal (like boost::transform_iterator)
As the other answer suggests, use a struct as the map's value and make one of its fields private, with possibly a conversion operator to int.

Moving keys out of std::map<> &&

I'd like to have let's say getKeys() function getting not-copiable keys out of a map:
class MyObj {
// ... complex, abstract class...
};
struct Comparator { bool operator()(std::unique_ptr<MyObj> const &a, std::unique_ptr<MyObj> const &b); };
std::vector<std::unique_ptr<MyObj>> getKeys(std::map<std::unique_ptr<MyObj>, int, Comparator> &&map) {
std::vector<std::unique_ptr<MyObj>> res;
for (auto &it : map) {
res.push_back(std::move(it.first));
}
return res;
}
But it is not working because the key in it (.first) is const. Any tips how to solve it? Note: In our environment I'm not allowed to use C++17 function std::map::extract().
Is it somehow ok to use const_cast because map will be destructed anyway?
res.push_back(std::move(const_cast<std::unique_ptr<MyObj> &>(it.first)));
I want to avoid cloning MyObj.
I know why keys of a std::map container cannot be modified but is it still disallowed for a map that is going to be destructed immediately after the key modification?
Note: In our environment I'm not allowed to use C++17 function std::map::extract().
Shame - it was introduced to solve this problem.
Is it somehow ok to use const_cast because map will be destructed anyway?
No.
I want to avoid cloning MyObj.
Sorry; you'll need to clone the keys at least.
I know why keys of a std::map container cannot be modified but is it still disallowed for a map that is going to be destructed immediately after the key modification?
Yes.
The map's internal machinery has no way of knowing that its destiny awaits.
Yes, it's still disallowed. Non-const access to keys is probably safe if you're just going to destroy the map afterwards, but it's not guaranteed to be safe by the standard, and the std::map interface doesn't offer any sort of relaxation of the rules which applies to rvalue references.
What std::map does have since C++17, though, is extract(), which rips a key-value pair out of the map entirely and returns it as a "node handle". This node handle provides non-const access to the key. So if you were to move the pointer out of that node handle, the eventual destruction would happen to an empty pointer.
Example:
#include <utility>
#include <memory>
#include <vector>
#include <map>
template <typename K, typename V>
std::vector<K> extractKeys(std::map<K, V> && map)
{
std::vector<K> res;
while(!map.empty())
{
auto handle = map.extract(map.begin());
res.emplace_back(std::move(handle.key()));
}
return std::move(res);
}
int main()
{
std::map<std::unique_ptr<int>, int> map;
map.emplace(std::make_pair(std::make_unique<int>(3), 4));
auto vec = extractKeys(std::move(map));
return *vec[0];
}
Answers persuaded me that I should avoid const_cast-ing. After some analysis I realized that usage of my map is quite isolated in the code so I could do a small refactor to avoid the const-issue.
Here is the result:
class MyObj {
// ... complex, abstract class...
};
struct Comparator { bool operator()(MyObj const *a, MyObj const *b); };
// key is a pointer only, value holds the key object and the effective "value"
struct KeyAndVal { std::unique_ptr<MyObj> key; int val; };
using MyMap = std::map<MyObj *, KeyAndVal, Comparator>;
// Example how emplace should be done
auto myEmplace(MyMap &map, std::unique_ptr<MyObj> key, int val) {
auto *keyRef = key.get(); // to avoid .get() and move in one expr below
return map.emplace(keyRef, KeyAndVal{ std::move(key), val });
}
std::vector<std::unique_ptr<MyObj>> getKeys(MyMap map) {
std::vector<std::unique_ptr<MyObj>> res;
for (auto &it : map) {
res.push_back(std::move(it.second.key));
}
// here 'map' is destroyed but key references are still valid
// (moved into return value).
return res;
}

access key in constructor of struct in a map

Use case: a buffer of records. Here is the basic idea.
Making it work requires that the constructor of the record struct knows the key, which is used as recordnumber, when an element is added to the map.
Of course, this can be done with more code, but this looks most elegant to me.
Minimally coded:
#include <whatever>
struct record
{
string foo;
record(unsigned irec) { foo=readrecord(irec); }
};
map<unsigned,record>recbuf;
int main()
{
// if the element is not yet in the map, it should be read.
string foo_ten=recbuf[10].foo;
// do something with the result
printf("foo_ten: %s\n",foo_ten.c_str());
return 0;
}
Edit1: code above will not work.
Any ideas how to get this to work?
Edit2:
I derived a mapplus class adding another map::operator[]:
template<class _Kty, class _Ty, class _Pr = less<_Kty>, class _Alloc = allocator<pair<const _Kty, _Ty> > >class mapplus :public map<_Kty, _Ty, _Pr, _Alloc>
{
public:
mapped_type& operator[](const _Kty &_Keyval)
{ // find element matching _Keyval or insert with default mapped
iterator _Where = _Mybase::lower_bound(_Keyval);
if (_Where == _Mybase::end()
|| _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode())))
_Where = _Mybase::emplace_hint(_Where,
_Keyval,
_Ty(_Keyval));
return (_Where->second);
}
};
This does work. I am still interested in comments pointing out to me that I did this in a needlessly complex etc. way. Did I? Can it be done with less ado?
So, you want record objects to be constructed using your record(unsigned) constructor, rather than the default constructor.
Unfortunately, there's no way to do this with operator[] (reference):
If k matches the key of an element in the container, the function
returns a reference to its mapped value.
If k does not match the key of any element in the container, the
function inserts a new element with that key and returns a reference
to its mapped value. Notice that this always increases the container
size by one, even if no mapped value is assigned to the element (the
element is constructed using its default constructor).
I would not recommend overloading operator[] for std::map, for me it seems like a bad design.
However, you can do it with other methods, like insert or emplace (C++11).
See, for example, this answer: Using std::map<K,V> where V has no usable default constructor
Tested example:
#include <map>
#include <sstream>
#include <iostream>
std::string readRecord(int id)
{
std::stringstream stream;
stream << id;
return stream.str();
}
struct Record
{
Record(int id)
: foo(readRecord(id))
{
}
std::string foo;
};
int main()
{
std::map<int, Record> m;
for (int i = 0; i < 10; ++i)
m.insert(std::make_pair(i, Record(i)));
std::cout << m.at(5).foo << std::endl;
// std::cout << m[7].foo << std::endl; // error 'Record::Record': no appropriate default constructor available
return 0;
}

Generic container for multiple data types in C++

Using C++, I'm trying to create a generic container class to handle multiple data types. It's a common problem with a variety of solutions, but I've found nothing as... intuitive as I've grown accustomed to in languages like Python or even VB/VBA...
So here's my scenario:
I've built a DataContainer class based on boost::any which I use to store multiple data types of multiple elements. I use a map declared as:
std::map<std::string, DataContainer* (or DataContainerBase*)>
where DataContainer is a class that encapsulates an object of the type:
std::list<boost::any>
along with convenience functions for managing / accessing the list.
However, in the end, I'm still forced to do type conversions outside the data container.
For example, if I were to store a list of int values in the map, accessing them would require:
int value = boost::any_cast<int>(map["myValue"]->get());
I'd rather the boost code be contained entirely within the data container structure, so I would only need type:
int value = map["myValue"]->get();
or, worst-case:
int value = map["myValue"]->get<int>();
Of course, I could enumerate my data types and do something like:
int value = map["myValue"]->get( TYPE_INT );
or write type-specific get() functions:
getInt(), getString(), getBool() ...
The problem with the last two options is that they are somewhat inflexible, requiring me to declare explicitly each type I wish to store in the container. The any_cast solution (which I have implemented and works) I suppose is fine, it's just... inelegant? I dunno. It seems I shouldn't need to employ the internal mechanics externally as well.
As I see it, passing the value without declaring the value type in the call to the DataContainer member function would require a void* solution (which is undesirable for obvious reasons), and using a "get()" call would require (so far as I can tell) a "virtual template" member function defined at the base class level, which, of course, isn't allowed.
As it is, I have a workable solution, and really, my use in this case is limited enough in scope that most any solutions will work well. But I am wondering if perhaps there's a more flexible way to manage a generic, multi-type data container than this.
If you want to introduce some sugar for this:
int value = boost::any_cast<int>(map["myValue"]->get());
then you might want to make the get() function to return a proxy object, defined +- like this:
struct Proxy {
boost::any& value;
Proxy(boost::any& value) : value(value) {}
template<typename T>
operator T() {
return boost::any_cast<T>(value);
}
};
Then this syntax would work:
int value = map["myValue"]->get();
// returns a proxy which gets converted by any_cast<int>
However I recommend to keep things explicit and just use that syntax:
int value = map["myValue"]->get<int>();
Here get doesn't return a proxy object with a template method, but is a template method itself (but does the same as the template conversion operator shown above).
Today I have done some source code for the purpose you want. I know that this question is so old, but maybe this little piece of code is helpful for someone. It is mainly based on boost:any.
/*
* AnyValueMap.hpp
*
* Created on: Jun 3, 2013
* Author: alvaro
*/
#ifndef ANYVALUEMAP_HPP_
#define ANYVALUEMAP_HPP_
#include <map>
#include <boost/any.hpp>
using namespace std;
template <class T>
class AnyValueMap {
public:
AnyValueMap(){}
virtual ~AnyValueMap(){}
private:
map<T, boost::any> container_;
typedef typename map<T, boost::any>::iterator map_iterator;
typedef typename map<T, boost::any>::const_iterator map_const_iterator;
public:
bool containsKey(const T key) const
{
return container_.find(key) != container_.end();
}
bool remove(const T key)
{
map_iterator it = container_.find(key);
if(it != container_.end())
{
container_.erase(it);
return true;
}
return false;
}
template <class V>
V getValue(const T key, const V defaultValue) const
{
map_const_iterator it = container_.find(key);
if(it != container_.end())
{
return boost::any_cast<V>(it->second);
}
return defaultValue;
}
template <class V>
V getValue(const T key) const
{
return boost::any_cast<V>(container_.at(key));
}
template <class V>
void setValue(const T key, const V value)
{
container_[key] = value;
}
};
#endif /* ANYVALUEMAP_HPP_ */
A simple usage example:
AnyValueMap<unsigned long> myMap;
myMap.setValue<double>(365, 1254.33);
myMap.setValue<int>(366, 55);
double storedDoubleValue = myMap.getValue<double>(365);
int storedIntValue = myMap.getValue<int>(366);

How to adapt a visitor interface to an iterator interface?

I'm wondering whether there is a good design pattern or idiom to realize the following:
You have an existing class that provides only a visitor interface, as follows
class Visitor {
public:
virtual ~Visitor() { }
virtual void visit(Node *n) = 0;
};
class Tree {
public:
void accept(Visitor *v);
};
And you want to have an interface that can be used as follows, which should iterate through the tree in the same order that the visitor would have its visit function called.
for(iterator it(...), ite(...); it != ite; ++it) {
/* process node */
}
The problem appears to be that when we just call visit, we are out of control, and can't temporarily "go back" to the loop body to execute the action for one node. This looks like it should occur regularly in real world programs. Any idea how to solve it?
In the general case, I don't think it's possible, at least not cleanly.
At least as it's usually defined, an iterator expects to deal with a homogeneous collection. I.e., an iterator is normally defined something like:
template <class Element>
class iterator // ...
...so a specific iterator can only work with elements of one specific type. The most you can do to work with differing types is create an iterator to (a pointer/reference to) a base class, and let it deal with objects of derived classes.
By contrast, it's pretty easy to write a visitor like this:
class MyVisitor {
public:
void VisitOneType(OneType const *element);
void VisitAnotherType(AnotherType const *element);
};
This can visit nodes of either OneType or AnotherType, even if the two are completely unrelated. Basically, you have one Visit member function in your Visitor class for every different type of class that it will be able to visit.
Looked at from a slightly different direction, an iterator is basically a specialized form of visitor that only works for one type of object. You exchange a little more control over the visitation pattern in exchange for losing the ability to visit unrelated types of objects.
If you only need to deal with one type (though that one type may be a base class, and the visited objects are of various derived types), then the obvious method would be to build a "bridge" class that visits objects (Tree nodes, in your example), and when its visit is called, it just copies the address of the node it's visiting into some collection that supports iterators:
template <class T>
class Bridge {
std::vector<T *> nodes;
public:
virtual void visit(T *n) {
nodes.push_back(n);
}
typedef std::vector<T *>::iterator iterator;
iterator begin() { return nodes.begin(); }
iterator end() { return nodes.end(); }
};
Using this would be a two-step process: first visit the nodes like a visitor normally would, then having collected together the nodes of interest you can iterate through them just like you would any other collection that provides iterators. At that point, your visitation pattern is limited only by the class of iterator provided by the collection you use in your bridge.
I had this problem in a real-world setting with an R-tree implementation that provided a visitor interface, whereas I needed an iterator interface. The suggestion by Jerry above works only if you can accept storing all the results in a collection. That may result in high memory consumption if your result set is huge and you don't really need to store them.
One solution that will work for sure is to launch the visitor in a separate thread and start waiting on a conditional variable for the results. When a visit call is made, you store the current result into a shared temp location, and use another conditional variable to wait for the next request. You signal the caller (main) thread's conditional variable before you wait on your own. The caller, which is implementing the iterator interface can then return the value stored at the temp location. During the next iteration, it could signal the visitor thread's conditional variable, and wait on its own for the next item. Unfortunately, this is somewhat costly if you do it on a per-item basis. You can buffer some items to improve the performance.
What we really need is an extra stack and to alternate between two contexts. This abstraction is provided by coroutines. In C++, boost::coroutine provides a clean implementation. Below I include a full example of how visitor pattern can be adapted into an iterator pattern.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/coroutine/coroutine.hpp>
template<typename Data>
class Visitor
{
public:
virtual ~Visitor() { }
virtual bool visit(Data const & data) = 0;
};
template <typename Data>
class Visitable
{
public:
virtual ~Visitable() {}
virtual void performVisits(Visitor<Data> & visitor) = 0;
};
// Assume we cannot change the code that appears above
template<typename Data>
class VisitableIterator : public Visitor<Data>
{
private:
typedef boost::coroutines::coroutine<void()> coro_t;
public:
VisitableIterator(Visitable<Data> & visitable)
: valid_(true), visitable_(visitable)
{
coro_ = coro_t(boost::bind(&VisitableIterator::visitCoro, this, _1));
}
bool isValid() const
{
return valid_;
}
Data const & getData() const
{
return *data_;
}
void moveToNext()
{
if(valid_)
coro_();
}
private:
void visitCoro(coro_t::caller_type & ca)
{
ca_ = & ca;
visitable_.performVisits(*static_cast<Visitor<Data> *>(this));
valid_ = false;
}
bool visit(Data const & data)
{
data_ = &data;
(*ca_)();
return false;
}
private:
bool valid_;
Data const * data_;
coro_t coro_;
coro_t::caller_type * ca_;
Visitable<Data> & visitable_;
};
// Example use below
class Counter : public Visitable<int>
{
public:
Counter(int start, int end)
: start_(start), end_(end) {}
void performVisits(Visitor<int> & visitor)
{
bool terminated = false;
for (int current=start_; !terminated && current<=end_; ++current)
terminated = visitor.visit(current);
}
private:
int start_;
int end_;
};
class CounterVisitor : public Visitor<int>
{
public:
bool visit(int const & data)
{
std::cerr << data << std::endl;
return false; // not terminated
}
};
int main(void)
{
{ // using a visitor
Counter counter(1, 100);
CounterVisitor visitor;
counter.performVisits(visitor);
}
{ // using an iterator
Counter counter(1, 100);
VisitableIterator<int> iter(static_cast<Visitable<int>&>(counter));
for (; iter.isValid(); iter.moveToNext()) {
int data = iter.getData();
std::cerr << data << std::endl;
}
}
return EXIT_SUCCESS;
}
Building traversal logic in the visitors implementations is indeed not flexible. A usable way to cleanly separate traversing composite structures from visitation may be done via visitor combinators (there are other papers, feel free to google for them).
These slides about the same topic may also be of interest. They explain how to get clean syntax à la boost::spirit rules.