Как создать пул смежной памяти не POD-типа? - PullRequest
0 голосов
/ 06 июля 2018

У меня есть сценарий, в котором несколько операций представлены следующим образом:

struct Op {
  virtual void Run() = 0;
};

struct FooOp : public Op {
  const std::vector<char> v;
  const std::string s;
  FooOp(const std::vector<char> &v, const std::string &s) : v(v), s(s) {}
  void Run() { std::cout << "FooOp::Run" << '\n'; }
};

// (...)

Мое приложение работает в несколько проходов. На каждом проходе я хочу создать множество этих операций, и в конце прохода я могу отменить их все одновременно. Поэтому я хотел бы заранее выделить часть памяти для этих операций и выделить новые операции из этой памяти. Я придумал следующий код:

class FooPool {
public:
  FooPool(int size) {
    foo_pool = new char[size * sizeof(FooOp)]; // what about FooOp alignment?
    cur = 0;
  }

  ~FooPool() { delete foo_pool; }

  FooOp *New(const std::vector<char> &v, const std::string &s) {
    return new (reinterpret_cast<FooOp*>(foo_pool) + cur) FooOp(v,s);
  }

  void Release() {
    for (int i = 0; i < cur; ++i) {
      (reinterpret_cast<FooOp*>(foo_pool)+i)->~FooOp();
    }
    cur = 0;
  }

private:
  char *foo_pool;
  int cur;
};

Кажется, это работает, но я уверен, что мне нужно как-то позаботиться о выравнивании FooOp. Более того, я даже не уверен, что этот подход жизнеспособен, поскольку операции не являются POD.

  • Мой подход некорректен? (скорее всего)
  • Какой лучший способ сделать это?
  • Есть ли способ восстановить существующую память, используя unique_ptr s?

Спасибо!

1 Ответ

0 голосов
/ 06 июля 2018

Я думаю, что этот код будет иметь аналогичные характеристики производительности без необходимости возиться с размещением нового и выровненного хранилища:

class FooPool {
public:
    FooPool(int size) {
        pool.reserve(size);
    }

    FooOp* New(const std::vector<char>& v, const std::string& s) {
        pool.emplace_back(v, s); // in c++17: return pool.emplace_back etc. etc.
        return &pool.back();
    }

    void Release() {
        pool.clear();
    }

private:
    std::vector<FooOp> pool;
}

Ключевой идеей здесь является то, что ваш FooPool в основном делает то, что делает std::vector.

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