/* * Copyright 2007, Hugo Santos. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Hugo Santos, hugosantos@gmail.com */ #ifndef _SLAB_MERGED_STRATEGY_H_ #define _SLAB_MERGED_STRATEGY_H_ #include // This slab strategy includes the ObjectLink at the end of each object and the // slab at the end of the allocated pages. It uses aligned allocations to // provide object to slab mapping with zero storage, thus there is only one // word of overhead per object. This is optimized for small objects. template class MergedLinkCacheStrategy : public BaseCacheStrategy { public: typedef typename BaseCacheStrategy::BaseSlab BaseSlab; typedef typename BaseCacheStrategy::Slab Slab; MergedLinkCacheStrategy(base_cache *parent) : BaseCacheStrategy(parent) {} static inline const void * LowerBoundary(void *object, size_t byteCount) { const uint8_t *null = (uint8_t *)NULL; return null + ((((uint8_t *)object) - null) & ~(byteCount - 1)); } BaseSlab *ObjectSlab(void *object) const { return _SlabInPages(LowerBoundary(object, _SlabSize())); } BaseSlab *NewSlab(uint32_t flags) { typename Backend::AllocationID id; void *pages; size_t byteCount = _SlabSize(); // in order to save a pointer per object or a hash table to // map objects to slabs we required this set of pages to be // aligned in a (pageCount * PAGE_SIZE) boundary. if (Backend::AllocatePages(Parent(), &id, &pages, byteCount, CACHE_ALIGN_TO_TOTAL | flags) < B_OK) return NULL; _SlabInPages(pages)->id = id; return BaseCacheStrategy::_ConstructSlab(_SlabInPages(pages), pages, byteCount - sizeof(Slab), this, NULL, NULL); } void ReturnSlab(BaseSlab *slab) { BaseCacheStrategy::_DestructSlab(slab, NULL, NULL); } private: size_t _SlabSize() const { size_t byteCount = BaseCacheStrategy::SlabSize(sizeof(Slab)); if (byteCount > Backend::kMaximumAlignedLength) byteCount = Backend::kMaximumAlignedLength; return byteCount; } base_cache *Parent() const { return BaseCacheStrategy::Parent(); } Slab *_SlabInPages(const void *pages) const { return (Slab *)(((uint8_t *)pages) + _SlabSize() - sizeof(Slab)); } }; #endif