summaryrefslogtreecommitdiff
path: root/src/bucketed-array.hpp
blob: 150fa66654fae61911bd32f7ad17eaddd38f313a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#ifndef PKE_BUCKETED_ARRAY_HPP
#define PKE_BUCKETED_ARRAY_HPP

#include <cstddef>
#include <cassert>

#include "pk.h"

constexpr pk_handle_bucket_index_T BucketContainerDefaultBucketCount = 16;
constexpr pk_handle_item_index_T BucketContainerDefaultItemCount = 256;

template<typename T, typename CT = struct pk_handle, pk_handle_item_index_T BKT_CNT = BucketContainerDefaultBucketCount>
struct BucketContainer {
	CT limits;
	CT pkeHandle;
	T* buckets[BKT_CNT];
	T& operator[](CT) const;
};

template<typename T, typename CT, pk_handle_item_index_T BKT_CNT>
T&
BucketContainer<T, CT, BKT_CNT>::operator[](CT handle) const {
	assert(handle.bucketIndex < this->limits.bucketIndex);
	assert(handle.itemIndex < this->limits.itemIndex);
	assert(handle.bucketIndex != this->pkeHandle.bucketIndex || handle.itemIndex < this->pkeHandle.itemIndex);
	return this->buckets[handle.bucketIndex][handle.itemIndex];
}

template<typename T, typename CT, pk_handle_item_index_T BKT_CNT>
void Buckets_Init(BucketContainer<T, CT, BKT_CNT> &bktContainer, size_t maxItemCount = BucketContainerDefaultItemCount) {
	bktContainer.limits.bucketIndex = BKT_CNT;
	bktContainer.limits.itemIndex = maxItemCount;
	bktContainer.pkeHandle.bucketIndex = 0;
	bktContainer.pkeHandle.itemIndex = 0;
	for (pk_handle_item_index_T i = 0; i < BKT_CNT; ++i) {
		bktContainer.buckets[i] = nullptr;
	}
	bktContainer.buckets[0] = pk_new<T>(maxItemCount);
}

template<typename T, typename CT, pk_handle_item_index_T BKT_CNT>
inline CT Buckets_NewHandle(BucketContainer<T, CT, BKT_CNT> &bktContainer) {
	CT returnValue = bktContainer.pkeHandle;
	bktContainer.pkeHandle.itemIndex += 1;
	if (bktContainer.pkeHandle.itemIndex >= bktContainer.limits.itemIndex) {
		bktContainer.pkeHandle.itemIndex = 0;
		bktContainer.pkeHandle.bucketIndex += 1;
		assert(bktContainer.pkeHandle.bucketIndex < bktContainer.limits.bucketIndex);
	}
	if (bktContainer.pkeHandle.itemIndex == 0) {
		bktContainer.buckets[bktContainer.pkeHandle.bucketIndex] = pk_new<T>(bktContainer.limits.itemIndex);
	}
	return returnValue;
}

template<typename T, typename CT, pk_handle_item_index_T BKT_CNT>
static inline constexpr void Buckets_Destroy(BucketContainer<T, CT, BKT_CNT> &bktContainer) {
	for (pk_handle_item_index_T i = 0; i <= bktContainer.pkeHandle.bucketIndex; ++i) {
		if (bktContainer.buckets[i] == nullptr) continue;
		pk_delete<T>(bktContainer.buckets[i], bktContainer.limits.itemIndex);
		bktContainer.buckets[i] = CAFE_BABE(T);
	}
}

#endif /* PKE_BUCKETED_ARRAY_HPP */