C ++ Надежный способ удалить все записи с UUID в качестве ключа - PullRequest
0 голосов
/ 27 апреля 2018

Итак, у меня есть куча std :: unordered_maps, у которых у всех есть общий ключ, но разные типы данных для данных. Я в основном сделал структуру, похожую на компонентную систему сущностей, ключом которой является класс сущностей, который содержит boost :: uuid.

Добавление работает хорошо, но я борюсь с удалением целых сущностей из программы. Я не могу найти надежный способ их удаления без ущерба для работающих систем (я не хочу разрешать удаление в середине кадра, чтобы избежать сбоя одного кадра из-за того, что значения были рассинхронизированы или заменены некоторыми значениями по умолчанию), или это очень медленно.

Прямо сейчас у меня есть bool в классе сущности, и каждый кадр программа проходит через КАЖДУЮ сущность и проверяет, имеет ли она значение true или нет. ЕСЛИ да, точка данных удалена с карты.

Однако меня это не устраивает.

Вот как выглядит средняя сущность:

    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)());
    }

};

Хорошо, и вот как выглядят карты:

typedef typename std::unordered_map<std::reference_wrapper<const Entity>,List<std::shared_ptr<t>>,EntityHasher,std::equal_to<const Entity>> mapType;

Список - это собственный класс, который я создал, который просто хранит вещи в двусвязном списке. Не о чем беспокоиться. Я сделал это, поскольку доступ к данным был проще, чем с помощью карты unordered_multi.

Что я пробовал:

  • Я пытался хранить ссылки на классы, содержащие карты, и просто напрямую удалял их без особого успеха.
  • Я пытался получить, чтобы при обращении к «мертвой» сущности она добавлялась к вектору в классе, хранящем неупорядоченную карту, а затем очищалась в отдельной функции, называемой «removeCorpses». Однако это привело к тому, что менее используемые компоненты оставались включенными слишком долго, и обычно это было просто очень нестабильно (возможно, я допустил ошибку при реализации)

Пожалуйста, предложите мне несколько хороших способов удаления сущности на всех картах с ключом без вмешательства в активный фрейм и т. Д.

1 Ответ

0 голосов
/ 28 апреля 2018

Вы можете использовать Boost.MultiIndex для создания структуры, похожей на карту, в которой трупы сначала располагаются во вторичном последовательном индексе, чтобы их можно было стереть при необходимости:

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<<"} ";
  }
}

выход

{0,0} {2,2} {4,4} {6,6} {8,8} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...