Skip to content

Commit

Permalink
refactoring templates
Browse files Browse the repository at this point in the history
Signed-off-by: Coldwings <coldwings@me.com>
  • Loading branch information
Coldwings committed Jan 2, 2024
1 parent e75a773 commit 500c278
Showing 1 changed file with 119 additions and 165 deletions.
284 changes: 119 additions & 165 deletions common/expirecontainer.h
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ class ExpireList : public ExpireContainer<T> {
using Base = ExpireContainer<T>;
using Base::Base;
using typename Base::Item;
bool keep_alive(const T& x, bool insert_if_not_exists) {
bool keep_alive(const T &x, bool insert_if_not_exists) {
return Base::keep_alive(Item(x), insert_if_not_exists);
}
};
Expand Down Expand Up @@ -251,49 +251,14 @@ class ObjectCacheBase : public ExpireContainerBase {
// the argument `key` plays the roles of (type-erased) key
int release(const Item& key_item, bool recycle = false);

template <typename ObjectCache, typename ItemPtr, typename ValEntity,
typename ValPtr>
class Borrow {
public:
ObjectCache* _oc;
ItemPtr _ref;
bool _recycle = false;

Borrow(ObjectCache* oc, ItemPtr ref, bool recycle)
: _oc(oc), _ref(ref), _recycle(recycle) {}
~Borrow() {
if (_ref) _oc->ref_release(_ref, _recycle);
}

Borrow() = delete;
Borrow(const Borrow&) = delete;
Borrow(Borrow&& rhs) { move(std::move(rhs)); }
void operator=(const Borrow&) = delete;
void operator=(Borrow&& rhs) { move(rhs); }

operator bool() const { return _ref; }

bool recycle() const { return _recycle; }

bool recycle(bool x) { return _recycle = x; }

protected:
ValPtr get_ptr() { return (ValPtr)_ref->_obj; }
void move(Borrow&& rhs) {
_oc = rhs._oc;
rhs._oc = nullptr;
_ref = rhs._ref;
rhs._ref = nullptr;
_recycle = rhs._recycle;
}
};

public:
template<typename KeyType, typename ValPtr>
class PtrItem
: public KeyedItem<Item, KeyType> {
template <typename KeyType, typename ValType>
class PtrItem : public KeyedItem<Item, KeyType> {
public:
using KeyedItem<Item, KeyType>::KeyedItem;
using typename KeyedItem<Item, KeyType>::InterfaceKey;
using ValPtr = ValType;
using ValEntity = typename std::remove_pointer<ValPtr>::type;
virtual PtrItem* construct() const override {
auto item = new PtrItem(this->_key);
item->_obj = nullptr;
Expand All @@ -302,14 +267,26 @@ class ObjectCacheBase : public ExpireContainerBase {
return item;
}
~PtrItem() override { delete (ValPtr)this->_obj; }
ValPtr get_ptr() { return (ValPtr)this->_obj; }
ValEntity& get_ref() { return *(ValPtr)this->_obj; }

ValPtr get() { return get_ptr(); }

static ValPtr create_default() { return new ValEntity(); }
template <typename Ctor>
static decltype(auto) initialize(const Ctor& ctor) {
return [&ctor](void* arg) { ((PtrItem*)arg)->_obj = ctor(); };
}
};

template<typename KeyType, typename ValEntity>
class ListItem
: public KeyedItem<Item, KeyType> {
template <typename KeyType, typename ValType>
class ListItem : public KeyedItem<Item, KeyType> {
public:
using ValPtr = ValType*;
using ValEntity = ValType;
ValEntity _list;
using KeyedItem<Item, KeyType>::KeyedItem;
using typename KeyedItem<Item, KeyType>::InterfaceKey;
virtual ListItem* construct() const override {
auto item = new ListItem(this->_key);
item->_obj = nullptr;
Expand All @@ -318,38 +295,59 @@ class ObjectCacheBase : public ExpireContainerBase {
return item;
}
~ListItem() { _list.delete_all(); }
ValPtr get_ptr() { return &this->_list; }
ValEntity& get_ref() { return this->_list; }

ValEntity& get() { return get_ref(); }

static ValEntity create_default() { return ValEntity(); }
template <typename Ctor>
static decltype(auto) initialize(const Ctor& ctor) {
return [&ctor](void* arg) {
((ListItem*)arg)->_list = ctor();
((ListItem*)arg)->_obj = arg;
};
}
};
};

template<typename KeyType, typename ValPtr, typename ValEntity, typename ObjectCache, typename ItemType>
class ObjectCacheCommon : public ObjectCacheBase {
public:
using Base = ObjectCacheBase;
using KeyedItem = Base::KeyedItem<Base::Item, KeyType>;
template <typename ObjectCache>
class Borrow {
public:
using Item = typename ObjectCache::Item;
ObjectCache* _oc;
Item* _ref;
bool _recycle = false;

using ItemKey = typename KeyedItem::ItemKey;
using InterfaceKey = typename KeyedItem::InterfaceKey;
using Item = ItemType;
using ItemPtr = ItemType*;
Borrow(ObjectCache* oc, Item* ref, bool recycle)
: _oc(oc), _ref(ref), _recycle(recycle) {}
~Borrow() {
if (_ref) _oc->ref_release(_ref, _recycle);
}

ObjectCacheCommon(uint64_t expiration) : Base(expiration, expiration / 16) {}
ObjectCacheCommon(uint64_t expiration, uint64_t timer_cycle)
: Base(expiration, timer_cycle) {}
Borrow() = delete;
Borrow(const Borrow&) = delete;
Borrow(Borrow&& rhs) { move(std::move(rhs)); }
void operator=(const Borrow&) = delete;
void operator=(Borrow&& rhs) { move(rhs); }

int ref_release(ItemPtr item, bool recycle = false) {
return Base::ref_release(item, recycle);
}
operator bool() const { return _ref; }

int release(const InterfaceKey& key, bool recycle = false) {
return Base::release(Item(key), recycle);
}
bool recycle() const { return _recycle; }

using iterator = typename ExpireContainerBase::TypedIterator<Item>;
iterator begin() { return Base::begin(); }
iterator end() { return Base::end(); }
iterator find(const InterfaceKey& key) {
return Base::find(KeyedItem(key));
}
bool recycle(bool x) { return _recycle = x; }

typename Item::ValPtr operator->() { return _ref->get_ptr(); }
typename Item::ValEntity& operator*() { return _ref->get_ref(); }

protected:
void move(Borrow&& rhs) {
_oc = rhs._oc;
rhs._oc = nullptr;
_ref = rhs._ref;
rhs._ref = nullptr;
_recycle = rhs._recycle;
}
};
};

// Resource pool based on reference count
Expand All @@ -358,126 +356,82 @@ class ObjectCacheCommon : public ObjectCacheBase {
// or findout the object, add reference count; when object release, reduce
// refcount. if some resource is not referenced, it will be put back to gc list
// waiting to release.
template <typename KeyType, typename ValPtr>
class ObjectCache
: public ObjectCacheCommon<
KeyType, ValPtr, typename std::remove_pointer<ValPtr>::type,
ObjectCache<KeyType, ValPtr>, ObjectCacheBase::PtrItem<KeyType, ValPtr>> {
protected:
using Item = ObjectCacheBase::PtrItem<KeyType, ValPtr>;
template <typename KeyType, typename ValType, typename ItemType>
class __ObjectCache : public ObjectCacheBase {
public:
using Base = ObjectCacheBase;
using Common = ObjectCacheCommon<
KeyType, ValPtr, typename std::remove_pointer<ValPtr>::type,
ObjectCache<KeyType, ValPtr>, Item>;
using Item = ItemType;
using KeyedItem = Base::KeyedItem<Base::Item, KeyType>;
using InterfaceKey = typename Item::InterfaceKey;
using ItemPtr = Item*;
using ValEntity = typename std::remove_pointer<ValPtr>::type;
using ValEntity = typename Item::ValEntity;
using Borrow = typename Base::Borrow<__ObjectCache>;

public:
using typename Common::iterator;

using Common::Common;
using Common::release;
using Common::ref_release;
using Common::begin;
using Common::end;
using Common::find;
__ObjectCache(uint64_t expiration) : Base(expiration, expiration / 16) {}
__ObjectCache(uint64_t expiration, uint64_t timer_cycle)
: Base(expiration, timer_cycle) {}

template <typename Constructor>
ItemPtr ref_acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
auto _ctor = [&](void* item) {
((Item*)item)->_obj = ctor();
};
// _ctor can always implicit cast to `Delegate<void*>`
auto _ctor = Item::initialize(ctor);
return (ItemPtr)Base::ref_acquire(Item(key), _ctor, failure_cooldown);
}

template <typename Constructor>
ValPtr acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
decltype(auto) acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
auto item = ref_acquire(key, ctor, failure_cooldown);
return (ValPtr)(item ? item->_obj : nullptr);
assert(item);
return item->get();
}

class Borrow: public Base::Borrow<Common, ItemPtr, ValEntity, ValPtr> {
public:
using Base::Borrow<Common, ItemPtr, ValEntity, ValPtr>::Borrow;
ValEntity& operator*() { return *Borrow::get_ptr(); }
ValPtr operator->() { return Borrow::get_ptr(); }
};

template <typename Constructor>
Borrow borrow(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
return Borrow(this, ref_acquire(key, ctor, failure_cooldown), false);
int ref_release(ItemPtr item, bool recycle = false) {
return Base::ref_release(item, recycle);
}

Borrow borrow(const InterfaceKey& key) {
return borrow(key, [] { return new ValEntity(); });
int release(const InterfaceKey& key, bool recycle = false) {
return Base::release(Item(key), recycle);
}
};

template <typename KeyType, typename NodeType>
class ObjectCache<KeyType, intrusive_list<NodeType>>
: public ObjectCacheCommon<KeyType, intrusive_list<NodeType>*,
intrusive_list<NodeType>,
ObjectCache<KeyType, intrusive_list<NodeType>>,
ObjectCacheBase::ListItem<KeyType, intrusive_list<NodeType>>> {
protected:
using ListType = intrusive_list<NodeType>;
using Item = ObjectCacheBase::ListItem<KeyType, ListType>;
using Base = ObjectCacheBase;
using Common = ObjectCacheCommon<KeyType, intrusive_list<NodeType>*,
intrusive_list<NodeType>,
ObjectCache<KeyType, intrusive_list<NodeType>>,
ObjectCacheBase::ListItem<KeyType, intrusive_list<NodeType>>>;
using InterfaceKey = typename Item::InterfaceKey;
using ItemPtr = Item*;

public:
using typename Common::iterator;

using Common::Common;
using Common::release;
using Common::ref_release;
using Common::begin;
using Common::end;
using Common::find;

template <typename Constructor>
ItemPtr ref_acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
auto _ctor = [&](void* item) {
((Item*)item)->_list = ctor();
// always not nullptr
((Item*)item)->_obj = item;
};
return (ItemPtr)ObjectCacheBase::ref_acquire(Item(key), _ctor, failure_cooldown);
using iterator = typename ExpireContainerBase::TypedIterator<Item>;
iterator begin() { return Base::begin(); }
iterator end() { return Base::end(); }
iterator find(const InterfaceKey& key) {
return Base::find(KeyedItem(key));
}

template <typename Constructor>
ListType& acquire(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
auto item = ref_acquire(key, ctor, failure_cooldown);
assert(item);
return item->_list;
Borrow borrow(const typename Item::InterfaceKey& key,
const Constructor& ctor, uint64_t failure_cooldown = 0) {
return Borrow(
this,
((__ObjectCache*)this)->ref_acquire(key, ctor, failure_cooldown),
false);
}

class Borrow: public Base::Borrow<Common, ItemPtr, ListType, ListType*> {
public:
using Base::Borrow<Common, ItemPtr, ListType, ListType*>::Borrow;
ListType& operator*() { return *this->_ref->_list; }
ListType* operator->() { return &this->_ref->_list; }
};

template <typename Constructor>
Borrow borrow(const InterfaceKey& key, const Constructor& ctor,
uint64_t failure_cooldown = 0) {
return Borrow(this, ref_acquire(key, ctor, failure_cooldown), false);
Borrow borrow(const typename Item::InterfaceKey& key) {
return borrow(key, &Item::create_default);
}
};

Borrow borrow(const InterfaceKey& key) {
return borrow(key, [] { return ListType(); });
}
template <typename KeyType, typename ValPtr>
class ObjectCache
: public __ObjectCache<KeyType, ValPtr,
ObjectCacheBase::PtrItem<KeyType, ValPtr>> {
public:
using __ObjectCache<
KeyType, ValPtr,
ObjectCacheBase::PtrItem<KeyType, ValPtr>>::__ObjectCache;
};

template <typename KeyType, typename NodeType>
class ObjectCache<KeyType, intrusive_list<NodeType>>
: public __ObjectCache<
KeyType, intrusive_list<NodeType>,
ObjectCacheBase::ListItem<KeyType, intrusive_list<NodeType>>> {
public:
using __ObjectCache<KeyType, intrusive_list<NodeType>,
ObjectCacheBase::ListItem<
KeyType, intrusive_list<NodeType>>>::__ObjectCache;
};

0 comments on commit 500c278

Please sign in to comment.