固定長データベース

継承クラスとなる固定長クラスの永続化ができたので、これで固定長データベース(Pool)の実装が可能です。

固定長データを扱う場合に、追加するだけなら固定長配列データベースでもあまり問題はないのですが、削除しようとした途端、削除した配列要素の管理が必要になります。まぁ、削除した要素を二度と使わないという手もありますが、そうもいきません。

固定長データベースでは、データを挿入するとデータに割り振られたIDが返り、データを取得したり削除したりするときには、そのIDでデータを指定することとします。

データが削除されるとそのIDはスタック(削除スタック)にプッシュされ、データが挿入されると削除スタックからIDをポップして利用します。削除スタックに何もなければ、固定長配列データベースを拡張するだけです。

template <class T> class Pool  {
public:
  Pool() {}
  Pool(const std::string &f) {
    initialize(f);
  }

  void
  initialize(const std::string &f) {
    std::string str = f;
    str.append("_p");
    pool.initialize(str);
    reservedOffset = pool.reserved(sizeof(size_t));
    str = f;
    str.append("_i");
    invalidObjects.initialize(str);
  }

  size_t insert() {
    size_t idx;
    try {
      idx = invalidObjects.front();
      invalidObjects.pop();
    } catch(...) {
      getPoolSize()++;
      idx = getPoolSize();
      if (idx >= pool.getSize()) {
        pool.resize(idx + 1);
      }
    }
    return idx;
  }

  size_t insert(T &t) {
    size_t idx = insert();
    pool.set(idx - 1, t);
    return idx;
  }

  void remove(size_t idx) {
    invalidObjects.push(idx);
  }

  void set(size_t idx, T &t) {
    pool.set(idx - 1, t);
  }

  T &at(size_t idx) {
    return pool.at(idx - 1);
  }
protected:
  Array<T> pool;
  Stack<size_t> invalidObjects;
  size_t reservedOffset;
  size_t &getPoolSize() {
    return *(size_t*)pool.getReservedVariable(reservedOffset);
  }

};

前:固定長配列データベースの改良

次:ポインタのエンコード