This commit is contained in:
2023-01-21 04:20:39 +08:00
54 changed files with 1006 additions and 255 deletions
+154 -66
View File
@@ -1,5 +1,6 @@
#pragma once
#include "types.h"
#include "gc.h"
#include <utility>
#include <limits>
#include <deque>
@@ -12,7 +13,7 @@ size_t count(const VT<T>& v) {
}
template <class T>
constexpr static inline size_t count(const T&) { return 1; }
constexpr static size_t count(const T&) { return 1; }
// TODO: Specializations for dt/str/none
template<class T, template<typename ...> class VT>
@@ -29,14 +30,19 @@ double avg(const VT<T>& v) {
return (sum<T>(v) / static_cast<double>(v.size));
}
template<class T, template<typename ...> class VT, class Ret>
void sqrt(const VT<T>& v, Ret& ret) {
for (uint32_t i = 0; i < v.size; ++i)
ret[i] = sqrt(v[i]);
}
template<class T, template<typename ...> class VT>
VT<double> sqrt(const VT<T>& v) {
VT<double> ret(v.size);
for (uint32_t i = 0; i < v.size; ++i) {
ret[i] = sqrt(v[i]);
}
sqrt(v, ret);
return ret;
}
template <class T>
T truncate(const T& v, const uint32_t precision) {
auto multiplier = pow(10, precision);
@@ -73,109 +79,153 @@ T min(const VT<T>& v) {
min_v = min_v < _v ? min_v : _v;
return min_v;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> mins(const VT<T>& arr) {
// simplify this using a template std::binary_function<T, T, bool> = std::less;
template<class T, template<typename ...> class VT, class Ret>
void mins(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
std::deque<std::pair<T, uint32_t>> cache;
decayed_t<VT, T> ret(len);
T min = std::numeric_limits<T>::max();
for (int i = 0; i < len; ++i) {
if (arr[i] < min)
min = arr[i];
ret[i] = min;
}
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> mins(const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
mins(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> maxs(const VT<T>& arr) {
template<class T, template<typename ...> class VT, class Ret>
void maxs(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
T max = std::numeric_limits<T>::min();
for (int i = 0; i < len; ++i) {
if (arr[i] > max)
max = arr[i];
ret[i] = max;
}
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> minw(uint32_t w, const VT<T>& arr) {
decayed_t<VT, T> maxs(const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
maxs(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void minw(uint32_t w, const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
std::deque<std::pair<T, uint32_t>> cache;
for (int i = 0; i < len; ++i) {
if (!cache.empty() && cache.front().second == i - w) cache.pop_front();
while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back();
cache.push_back({ arr[i], i });
ret[i] = cache.front().first;
}
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> maxw(uint32_t w, const VT<T>& arr) {
decayed_t<VT, T> minw(uint32_t w, const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
minw(w, arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void maxw(uint32_t w, const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
std::deque<std::pair<T, uint32_t>> cache;
for (int i = 0; i < len; ++i) {
if (!cache.empty() && cache.front().second == i - w) cache.pop_front();
while (!cache.empty() && cache.back().first > arr[i]) cache.pop_back();
while (!cache.empty() && cache.back().first < arr[i]) cache.pop_back();
cache.push_back({ arr[i], i });
arr[i] = cache.front().first;
ret[i] = cache.front().first;
}
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<T>> ratiow(uint32_t w, const VT<T>& arr) {
inline decayed_t<VT, T> maxw(uint32_t w, const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
maxw(w, arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void ratiow(uint32_t w, const VT<T>& arr, Ret& ret) {
typedef std::decay_t<types::GetFPType<T>> FPType;
uint32_t len = arr.size;
if (arr.size <= w)
len = 1;
w = w > len ? len : w;
decayed_t<VT, FPType> ret(arr.size);
ret[0] = 0;
for (uint32_t i = 0; i < w; ++i)
ret[i] = arr[i] / (FPType)arr[0];
for (uint32_t i = w; i < arr.size; ++i)
ret[i] = arr[i] / (FPType) arr[i - w];
}
template<class T, template<typename ...> class VT>
inline decayed_t<VT, types::GetFPType<T>> ratiow(uint32_t w, const VT<T>& arr) {
typedef std::decay_t<types::GetFPType<T>> FPType;
decayed_t<VT, FPType> ret(arr.size);
ratiow(w, arr, ret);
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<T>> ratios(const VT<T>& arr) {
inline decayed_t<VT, types::GetFPType<T>> ratios(const VT<T>& arr) {
return ratiow(1, arr);
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetLongType<T>> sums(const VT<T>& arr) {
template<class T, template<typename ...> class VT, class Ret>
inline void ratios(const VT<T>& arr, Ret& ret) {
return ratiow(1, arr, ret);
}
template<class T, template<typename ...> class VT, class Ret>
void sums(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, types::GetLongType<T>> ret(len);
uint32_t i = 0;
if (len) ret[i++] = arr[0];
for (; i < len; ++i)
ret[i] = ret[i - 1] + arr[i];
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgs(const VT<T>& arr) {
inline decayed_t<VT, types::GetLongType<T>> sums(const VT<T>& arr) {
decayed_t<VT, types::GetLongType<T>> ret(arr.size);
sums(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void avgs(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
typedef types::GetFPType<types::GetLongType<T>> FPType;
decayed_t<VT, FPType> ret(len);
uint32_t i = 0;
types::GetLongType<T> s;
if (len) s = ret[i++] = arr[0];
for (; i < len; ++i)
ret[i] = (s += arr[i]) / (FPType)(i + 1);
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgs(const VT<T>& arr) {
typedef types::GetFPType<types::GetLongType<T>> FPType;
decayed_t<VT, FPType> ret(arr.size);
avgs(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void sumw(uint32_t w, const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, types::GetLongType<T>> ret(len);
uint32_t i = 0;
w = w > len ? len : w;
if (len) ret[i++] = arr[0];
@@ -183,11 +233,17 @@ decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
ret[i] = ret[i - 1] + arr[i];
for (; i < len; ++i)
ret[i] = ret[i - 1] + arr[i] - arr[i - w];
return ret;
}
template<class T, template<typename ...> class VT>
void avgw(uint32_t w, const VT<T>& arr, decayed_t<vector_type, types::GetFPType<types::GetLongType<T>>>& ret) {
decayed_t<VT, types::GetLongType<T>> sumw(uint32_t w, const VT<T>& arr) {
decayed_t<VT, types::GetLongType<T>> ret(arr.size);
sumw(w, arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void avgw(uint32_t w, const VT<T>& arr, Ret& ret) {
typedef types::GetFPType<types::GetLongType<T>> FPType;
const uint32_t& len = arr.size;
uint32_t i = 0;
@@ -201,26 +257,19 @@ void avgw(uint32_t w, const VT<T>& arr, decayed_t<vector_type, types::GetFPType<
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgw(uint32_t w, const VT<T>& arr) {
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> avgw(uint32_t w, const VT<T>& arr) {
typedef types::GetFPType<types::GetLongType<T>> FPType;
const uint32_t& len = arr.size;
decayed_t<VT, FPType> ret(len);
uint32_t i = 0;
types::GetLongType<T> s{};
w = w > len ? len : w;
if (len) s = ret[i++] = arr[0];
for (; i < w; ++i)
ret[i] = (s += arr[i]) / (FPType)(i + 1);
for (; i < len; ++i)
ret[i] = ret[i - 1] + (arr[i] - arr[i - w]) / (FPType)w;
avgw(w, arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, bool sd = false>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT<T>& arr) {
template<class T, template<typename ...> class VT, class Ret, bool sd = false>
void varw(uint32_t w, const VT<T>& arr,
Ret& ret) {
using FPType = types::GetFPType<types::GetLongType<T>>;
const uint32_t& len = arr.size;
decayed_t<VT, FPType> ret(len);
uint32_t i = 0;
types::GetLongType<T> s{};
w = w > len ? len : w;
@@ -252,7 +301,14 @@ decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT
if constexpr(sd)
if(i)
ret[i-1] = sqrt(ret[i-1]);
}
template<class T, template<typename ...> class VT, bool sd = false>
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> varw(uint32_t w, const VT<T>& arr) {
using FPType = types::GetFPType<types::GetLongType<T>>;
decayed_t<VT, FPType> ret(arr.size);
varw<T, VT, decayed_t<VT, types::GetFPType<types::GetLongType<T>>>, sd>(w, arr, ret);
return ret;
}
@@ -274,11 +330,10 @@ types::GetFPType<types::GetLongType<decays<T>>> var(const VT<T>& arr) {
return (ssq - s * s / (FPType)(len + 1)) / (FPType)(len + 1);
}
template<class T, template<typename ...> class VT, bool sd = false>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
template<class T, template<typename ...> class VT, class Ret, bool sd = false>
void vars(const VT<T>& arr, Ret& ret) {
typedef types::GetFPType<types::GetLongType<T>> FPType;
const uint32_t& len = arr.size;
decayed_t<VT, FPType> ret(len);
uint32_t i = 0;
types::GetLongType<T> s{};
FPType MnX{};
@@ -298,70 +353,103 @@ decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
ret[i] = MnX / (FPType)(i + 1);
if constexpr(sd) ret[i] = sqrt(ret[i]);
}
}
template<class T, template<typename ...> class VT, bool sd = false>
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> vars(const VT<T>& arr) {
typedef types::GetFPType<types::GetLongType<T>> FPType;
decayed_t<VT, FPType> ret(arr.size);
vars<T, VT, decayed_t<VT, types::GetFPType<types::GetLongType<T>>>, sd>(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT>
types::GetFPType<types::GetLongType<decays<T>>> stddev(const VT<T>& arr) {
inline types::GetFPType<types::GetLongType<decays<T>>> stddev(const VT<T>& arr) {
return sqrt(var(arr));
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevs(const VT<T>& arr) {
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevs(const VT<T>& arr) {
return vars<T, VT, true>(arr);
}
template<class T, template<typename ...> class VT>
decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevw(uint32_t w, const VT<T>& arr) {
inline decayed_t<VT, types::GetFPType<types::GetLongType<T>>> stddevw(uint32_t w, const VT<T>& arr) {
return varw<T, VT, true>(w, arr);
}
template<class T, template<typename ...> class VT, class Ret>
inline auto stddevs(const VT<T>& arr, Ret& ret) {
return vars<T, VT, Ret, true>(arr, ret);
}
template<class T, template<typename ...> class VT, class Ret>
inline auto stddevw(uint32_t w, const VT<T>& arr, Ret& ret) {
return varw<T, VT, Ret, true>(w, arr, ret);
}
// use getSignedType
template<class T, template<typename ...> class VT>
decayed_t<VT, T> deltas(const VT<T>& arr) {
template<class T, template<typename ...> class VT, class Ret>
void deltas(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
uint32_t i = 0;
if (len) ret[i++] = 0;
for (; i < len; ++i)
ret[i] = arr[i] - arr[i - 1];
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> prev(const VT<T>& arr) {
inline decayed_t<VT, T> deltas(const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
deltas(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void prev(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
uint32_t i = 0;
if (len) ret[i++] = arr[0];
for (; i < len; ++i)
ret[i] = arr[i - 1];
return ret;
}
template<class T, template<typename ...> class VT>
decayed_t<VT, T> aggnext(const VT<T>& arr) {
inline decayed_t<VT, T> prev(const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
prev(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT, class Ret>
void aggnext(const VT<T>& arr, Ret& ret) {
const uint32_t& len = arr.size;
decayed_t<VT, T> ret(len);
uint32_t i = 1;
for (; i < len; ++i)
ret[i - 1] = arr[i];
if (len > 0) ret[len - 1] = arr[len - 1];
}
template<class T, template<typename ...> class VT>
inline decayed_t<VT, T> aggnext(const VT<T>& arr) {
decayed_t<VT, T> ret(arr.size);
aggnext(arr, ret);
return ret;
}
template<class T, template<typename ...> class VT>
T last(const VT<T>& arr) {
if (!arr.size) return 0;
const uint32_t& len = arr.size;
return arr[arr.size - 1];
}
template<class T, template<typename ...> class VT>
T first(const VT<T>& arr) {
if (!arr.size) return 0;
const uint32_t& len = arr.size;
return arr[0];
}
#define __DEFAULT_AGGREGATE_FUNCTION__(NAME, RET) \
template <class T> constexpr T NAME(const T& v) { return RET; }
+50 -7
View File
@@ -1,9 +1,43 @@
#pragma once
#ifndef __AQ_USE_THREADEDGC__
#include <atomic>
class GC {
private:;
class ScratchSpace {
public:
void* ret;
char* scratchspace;
size_t ptr;
size_t cnt;
size_t capacity;
size_t initial_capacity;
void* temp_memory_fractions;
//uint8_t status;
// record maximum size
constexpr static uint8_t Grow = 0x1;
// no worry about overflow
constexpr static uint8_t Use = 0x0;
void init(size_t initial_capacity);
// apply for memory
void* alloc(uint32_t sz);
void register_ret(void* ret);
// reorganize memory space
void release();
// reset status of the scratch space
void reset();
// reset scratch space to initial capacity.
void cleanup();
};
#ifndef __AQ_USE_THREADEDGC__
class GC {
private:
size_t max_slots,
interval, forced_clean,
forceclean_timer = 0;
@@ -18,7 +52,6 @@ private:;
std::atomic<uint64_t> current_size;
volatile bool lock;
using gc_deallocator_t = void (*)(void*);
// maybe use volatile std::thread::id instead
protected:
void acquire_lock();
@@ -29,28 +62,38 @@ protected:
void terminate_daemon();
public:
void reg(void* v, uint32_t sz = 1,
ScratchSpace scratch;
void reg(void* v, uint32_t sz = 0xffffffff,
void(*f)(void*) = free
);
uint32_t get_threshold() const {
return threshould;
}
GC(
uint64_t max_size = 0xfffffff, uint32_t max_slots = 4096,
uint32_t interval = 10000, uint32_t forced_clean = 1000000,
uint32_t threshould = 64 //one seconds
uint32_t threshould = 64, //one seconds
uint32_t scratch_sz = 0x1000000 // 16 MB
) : max_size(max_size), max_slots(max_slots),
interval(interval), forced_clean(forced_clean),
threshould(threshould) {
start_deamon();
GC::gc_handle = this;
this->scratch.init(1);
} // 256 MB
~GC(){
terminate_daemon();
scratch.cleanup();
}
static GC* gc_handle;
static ScratchSpace *scratch_space;
template <class T>
constexpr static inline gc_deallocator_t _delete(T*){
static inline gc_deallocator_t _delete(T*) {
return [](void* v){
delete (T*)v;
};
-4
View File
@@ -132,7 +132,3 @@ namespace ankerl::unordered_dense{
struct hash<std::tuple<Types...>> : public hasher<Types...>{ };
}
struct aq_hashtable_value_t {
uint32_t id;
uint32_t cnt;
};
+6
View File
@@ -4,6 +4,7 @@
#include <string>
#include <limits>
#include <cstring>
#include <string_view>
template <class ...Types>
std::string generate_printf_string(const char* sep = " ", const char* end = "\n") {
std::string str;
@@ -25,6 +26,11 @@ inline decltype(auto) print_hook<bool>(const bool& v) {
return v? "true" : "false";
}
template<>
inline decltype(auto) print_hook<std::string_view>(const std::string_view& v) {
return v.data();
}
extern char* gbuf;
void setgbuf(char* buf = 0);
+77
View File
@@ -55,6 +55,7 @@ void print<bool>(const bool&v, const char* delimiter){
std::cout<< (v?"true":"false") << delimiter;
}
template<class T>
T getInt(const char*& buf){
T ret = 0;
@@ -451,6 +452,9 @@ void GC::reg(void* v, uint32_t sz, void(*f)(void*)) { //~ 40ns expected v. free
f(v);
return;
}
else if (sz == 0xffffffff)
sz = this->threshould;
auto _q = static_cast<memoryqueue_t>(q);
while(lock);
++alive_cnt;
@@ -464,6 +468,72 @@ void GC::reg(void* v, uint32_t sz, void(*f)(void*)) { //~ 40ns expected v. free
#endif
inline GC* GC::gc_handle = nullptr;
inline ScratchSpace* GC::scratch_space = nullptr;
void ScratchSpace::init(size_t initial_capacity) {
ret = nullptr;
scratchspace = static_cast<char*>(malloc(initial_capacity));
ptr = cnt = 0;
capacity = initial_capacity;
this->initial_capacity = initial_capacity;
temp_memory_fractions = new vector_type<void*>();
}
inline void* ScratchSpace::alloc(uint32_t sz){
ptr = this->cnt;
this->cnt += sz; // major cost
if (this->cnt > capacity) {
[[unlikely]]
capacity = this->cnt + (capacity >> 1);
auto vec_tmpmem_fractions = static_cast<vector_type<char *>*>(temp_memory_fractions);
vec_tmpmem_fractions->emplace_back(scratchspace);
scratchspace = static_cast<char*>(malloc(capacity));
ptr = 0;
}
return scratchspace + ptr;
}
inline void ScratchSpace::register_ret(void* ret){
this->ret = ret;
}
inline void ScratchSpace::release(){
ptr = cnt = 0;
auto vec_tmpmem_fractions =
static_cast<vector_type<void*>*>(temp_memory_fractions);
if (vec_tmpmem_fractions->size) {
[[unlikely]]
for(auto& mem : *vec_tmpmem_fractions){
//free(mem);
GC::gc_handle->reg(mem);
}
vec_tmpmem_fractions->clear();
}
}
inline void ScratchSpace::reset() {
this->release();
ret = nullptr;
if (capacity != initial_capacity){
capacity = initial_capacity;
scratchspace = static_cast<char*>(realloc(scratchspace, capacity));
}
}
void ScratchSpace::cleanup(){
auto vec_tmpmem_fractions =
static_cast<vector_type<void*>*>(temp_memory_fractions);
if (vec_tmpmem_fractions->size) {
for(auto& mem : *vec_tmpmem_fractions){
free(mem);
//GC::gc_handle->reg(mem);
}
vec_tmpmem_fractions->clear();
}
delete vec_tmpmem_fractions;
free(this->scratchspace);
}
#include "dragonbox/dragonbox_to_chars.hpp"
@@ -537,4 +607,11 @@ aq_to_chars<types::timestamp_t>(void* value, char* buffer) {
return buffer;
}
template<>
char*
aq_to_chars<std::string_view>(void* value, char* buffer){
const auto& src = *static_cast<std::string_view*>(value);
memcpy(buffer, src.data(), src.size());
return buffer + src.size();
}
+1
View File
@@ -161,6 +161,7 @@ template<> char* aq_to_chars<char*>(void* , char*);
template<> char* aq_to_chars<types::date_t>(void* , char*);
template<> char* aq_to_chars<types::time_t>(void* , char*);
template<> char* aq_to_chars<types::timestamp_t>(void* , char*);
template<> char* aq_to_chars<std::string_view>(void* , char*);
typedef int (*code_snippet)(void*);
template <class _This_Struct>
+9 -5
View File
@@ -6,6 +6,8 @@
#include "monetdb_conn.h"
#include "monetdbe.h"
#include "table.h"
#include <thread>
#undef ERROR
#undef static_assert
@@ -73,11 +75,11 @@ void Server::connect(Context *cxt){
printf("Error: Server %p already connected. Restart? (Y/n). \n", server);
char c[50];
std::cin.getline(c, 49);
for(int i = 0; i < 50; ++i){
for(int i = 0; i < 50; ++i) {
if (!c[i] || c[i] == 'y' || c[i] == 'Y'){
monetdbe_close(*server);
free(*server);
this->server = 0;
this->server = nullptr;
break;
}
else if(c[i]&&!(c[i] == ' ' || c[i] == '\t'))
@@ -86,7 +88,10 @@ void Server::connect(Context *cxt){
}
server = (monetdbe_database*)malloc(sizeof(monetdbe_database));
auto ret = monetdbe_open(server, nullptr, nullptr);
monetdbe_options ops;
AQ_ZeroMemory(ops);
ops.nr_threads = std::thread::hardware_concurrency();
auto ret = monetdbe_open(server, nullptr, &ops);
if (ret == 0){
status = true;
this->server = server;
@@ -148,8 +153,7 @@ void Server::print_results(const char* sep, const char* end){
szs [i] = monetdbe_type_szs[cols[i]->type];
header_string = header_string + cols[i]->name + sep + '|' + sep;
}
const size_t l_sep = strlen(sep) + 1;
if (header_string.size() - l_sep >= 0)
if (const size_t l_sep = strlen(sep) + 1; header_string.size() >= l_sep)
header_string.resize(header_string.size() - l_sep);
header_string += end + std::string(header_string.size(), '=') + end;
fputs(header_string.c_str(), stdout);
+39 -15
View File
@@ -191,6 +191,21 @@ constexpr prt_fn_t monetdbe_prtfns[] = {
aq_to_chars<std::nullptr_t>
};
#ifndef __AQ_USE_THREADEDGC__
void aq_init_gc(void *handle, Context* cxt)
{
typedef void (*aq_gc_init_t) (Context*);
if (handle && cxt){
auto sym = dlsym(handle, "__AQ_Init_GC__");
if(sym){
((aq_gc_init_t)sym)(cxt);
}
}
}
#else //__AQ_USE_THREADEDGC__
#define aq_init_gc(h, c)
#endif //__AQ_USE_THREADEDGC__
#include "monetdbe.h"
#undef max
#undef min
@@ -280,6 +295,7 @@ void initialize_module(const char* module_name, void* module_handle, Context* cx
printf("Warning: module %s have no session support.\n", module_name);
}
}
#pragma endregion
int dll_main(int argc, char** argv, Context* cxt){
aq_timer timer;
@@ -363,12 +379,7 @@ start:
recorded_queries.emplace_back(copy_lpstr("N"));
}
handle = dlopen(proc_name, RTLD_NOW);
#ifndef __AQ_USE_THREADEDGC__
{
typedef void (*aq_gc_init_t) (Context*);
((aq_gc_init_t)dlsym(handle, "__AQ_Init_GC__"))(cxt);
}
#endif
aq_init_gc(handle, cxt);
if (procedure_recording) {
recorded_libraries.emplace_back(handle);
}
@@ -474,11 +485,13 @@ start:
p.__rt_loaded_modules = static_cast<void**>(
malloc(sizeof(void*) * p.postproc_modules));
for(uint32_t j = 0; j < p.postproc_modules; ++j){
auto pj = dlopen(p.name, RTLD_NOW);
auto pj = dlopen((procedure_root + p.name + std::to_string(j) + ".so").c_str(), RTLD_NOW);
if (pj == nullptr){
printf("Error: failed to load module %s\n", p.name);
return true;
}
aq_init_gc(pj, cxt);
p.__rt_loaded_modules[j] = pj;
}
}
@@ -503,6 +516,7 @@ start:
};
const auto& load_proc_fromfile = [&](StoredProcedure& p) {
auto config_name = procedure_root + p.name + ".aqp";
puts(p.name);
auto fp = fopen(config_name.c_str(), "rb");
if(fp == nullptr){
puts("ERROR: Procedure not found on disk.");
@@ -517,14 +531,17 @@ start:
p.queries = static_cast<char**>(malloc(sizeof(char*) * p.cnt));
p.queries[0] = static_cast<char*>(malloc(sizeof(char) * queries_size));
fread(&p.queries[0], queries_size, 1, fp);
fread(p.queries[0], 1, queries_size, fp);
for(uint32_t j = 1; j < p.cnt; ++j){
p.queries[j] = p.queries[j-1];
while(*p.queries[j] != '\0')
while(*(p.queries[j]) != '\0')
++p.queries[j];
++p.queries[j];
puts(p.queries[j-1]);
}
fclose(fp);
p.__rt_loaded_modules = 0;
return load_modules(p);
};
switch(n_recvd[i][1]){
@@ -553,18 +570,22 @@ start:
auto _proc = cxt->stored_proc.find(proc_name);
if (_proc == cxt->stored_proc.end()){
printf("Procedure %s not found. Trying load from disk.\n", proc_name);
if (load_proc_fromfile(current_procedure)){
current_procedure.name = copy_lpstr(proc_name);
if (!load_proc_fromfile(current_procedure)){
cxt->stored_proc.insert_or_assign(proc_name, current_procedure);
}
else {
continue;
}
}
else{
current_procedure = _proc->second;
n_recv = current_procedure.cnt;
n_recvd = current_procedure.queries;
load_modules(current_procedure);
procedure_replaying = true;
goto start; // yes, I know, refactor later!!
}
n_recv = current_procedure.cnt;
n_recvd = current_procedure.queries;
load_modules(current_procedure);
procedure_replaying = true;
goto start; // yes, I know, refactor later!!
}
break;
case 'D': // delete procedure
@@ -572,6 +593,9 @@ start:
case 'S': //save procedure
break;
case 'L': //load procedure
if (!load_proc_fromfile(current_procedure)) {
cxt->stored_proc.insert_or_assign(proc_name, current_procedure);
}
break;
case 'd': // display all procedures
for(const auto& p : cxt->stored_proc){
+49 -13
View File
@@ -10,6 +10,7 @@
#include <algorithm>
#include <cstdarg>
#include <vector>
#include <string_view>
#include "io.h"
#include "hasher.h"
@@ -35,7 +36,8 @@ struct ColRef_cstorage {
int ty; // what if enum is not int?
};
template <template <class...> class VT, class T>
template <template <class...> class VT, class T,
std::enable_if_t<std::is_base_of_v<vector_base<T>, VT<T>>>* = nullptr>
std::ostream& operator<<(std::ostream& os, const VT<T>& v)
{
v.out();
@@ -142,7 +144,7 @@ public:
vector_type<_Ty>::operator=(vt);
return *this;
}
ColRef<_Ty>& operator =(ColRef<_Ty>&& vt) {
ColRef<_Ty>& operator =(ColRef<_Ty>&& vt) noexcept {
vector_type<_Ty>::operator=(std::move(vt));
return *this;
@@ -289,6 +291,7 @@ public:
uint32_t len = end - start;
return ColView<_Ty>(orig, idxs.subvec(start, end));
}
ColRef<_Ty> subvec_deep(uint32_t start, uint32_t end) const {
uint32_t len = end - start;
ColRef<_Ty> subvec(len);
@@ -329,7 +332,7 @@ template<class ...Types> struct TableInfo;
template<class ...Types> struct TableView;
template <long long _Index, bool order = true, class... _Types>
constexpr inline auto& get(const TableInfo<_Types...>& table) noexcept {
constexpr auto& get(const TableInfo<_Types...>& table) noexcept {
if constexpr (order)
return *(ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>> *) & (table.colrefs[_Index]);
else
@@ -337,7 +340,7 @@ constexpr inline auto& get(const TableInfo<_Types...>& table) noexcept {
}
template <long long _Index, class... _Types>
constexpr inline ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>>& get(const TableView<_Types...>& table) noexcept {
constexpr ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>>& get(const TableView<_Types...>& table) noexcept {
return *(ColRef<std::tuple_element_t<_Index, std::tuple<_Types...>>> *) & (table.info.colrefs[_Index]);
}
@@ -348,9 +351,6 @@ struct is_vector_impl<ColView<V>> : std::true_type {};
template <class V>
struct is_vector_impl<vector_type<V>> : std::true_type {};
template<class ...Types>
struct TableView;
template<class ...Types>
struct TableInfo {
const char* name;
@@ -459,8 +459,7 @@ struct TableInfo {
std::string header_string = std::string();
for (uint32_t i = 0; i < sizeof...(Types); ++i)
header_string += std::string(this->colrefs[i].name) + sep + '|' + sep;
const size_t l_sep = strlen(sep) + 1;
if (header_string.size() - l_sep >= 0)
if (const size_t l_sep = strlen(sep) + 1; header_string.size() >= l_sep)
header_string.resize(header_string.size() - l_sep);
header_string += end + std::string(header_string.size(), '=') + end;
return header_string;
@@ -487,6 +486,7 @@ struct TableInfo {
if (header_string.size() - l_sep >= 0)
header_string.resize(header_string.size() - l_sep);
}
const auto& prt_loop = [&fp, &view, &printf_string, *this, &limit](const auto& f) {
#ifdef __AQ__HAS__INT128__
constexpr auto num_hge = count_type<__int128_t, __uint128_t>((tuple_type*)(0));
@@ -531,7 +531,7 @@ struct TableInfo {
}
}
template <int ...vals> struct applier {
inline constexpr static void apply(const TableInfo<Types...>& t, const char* __restrict sep = ",", const char* __restrict end = "\n",
constexpr static void apply(const TableInfo<Types...>& t, const char* __restrict sep = ",", const char* __restrict end = "\n",
const vector_type<uint32_t>* __restrict view = nullptr, FILE* __restrict fp = nullptr, uint32_t limit = std::numeric_limits<uint32_t>::max()
)
{
@@ -656,11 +656,11 @@ struct TableView {
};
template <class T>
constexpr static inline bool is_vector(const ColRef<T>&) {
constexpr static bool is_vector(const ColRef<T>&) {
return true;
}
template <class T>
constexpr static inline bool is_vector(const vector_type<T>&) {
constexpr static bool is_vector(const vector_type<T>&) {
return true;
}
@@ -910,6 +910,42 @@ VT<bool> operator >(const T2& lhs, const VT<T1>& rhs) {
return ret;
}
#define _AQ_OP_(x) __AQ_OP__##x
#define __AQ_OP__add +
#define __AQ_OP__minus -
#define __AQ_OP__div *
#define __AQ_OP__mul /
#define __AQ_OP__and &
#define __AQ_OP__or |
#define __AQ_OP__xor ^
#define __AQ_OP__gt >
#define __AQ_OP__lt <
#define __AQ_OP__gte >=
#define __AQ_OP__lte <=
#define __AQ_OP__eq ==
#define __AQ_OP__neq !=
#define __D_AQOP(x) \
template <class T1, class T2, template<typename> class VT, class Ret>\
void aqop_##x (const VT<T1>& lhs, const VT<T2>& rhs, Ret& ret){\
for (uint32_t i = 0; i < ret.size; ++i)\
ret[i] = lhs[i] _AQ_OP_(x) rhs[i];\
}
__D_AQOP(add)
__D_AQOP(minus)
__D_AQOP(div)
__D_AQOP(mul)
__D_AQOP(and)
__D_AQOP(or)
__D_AQOP(xor)
__D_AQOP(gt)
__D_AQOP(lt)
__D_AQOP(gte)
__D_AQOP(lte)
__D_AQOP(eq)
__D_AQOP(neq)
template <class ...Types>
void print(const TableInfo<Types...>& v, const char* delimiter = " ", const char* endline = "\n") {
@@ -919,6 +955,7 @@ template <class ...Types>
void print(const TableView<Types...>& v, const char* delimiter = " ", const char* endline = "\n") {
v.print(delimiter, endline);
}
template <class T>
void print(const T& v, const char* delimiter = " ") {
std::cout << v << delimiter;
@@ -933,7 +970,6 @@ void print<__uint128_t>(const __uint128_t& v, const char* delimiter);
#endif
template <>
void print<bool>(const bool& v, const char* delimiter);
template <class T>
void inline print_impl(const T& v, const char* delimiter, const char* endline) {
for (const auto& vi : v) {
+2 -2
View File
@@ -13,7 +13,7 @@ long long testing_throughput(uint32_t n_jobs, bool prompt = true){
auto tp = ThreadPool(thread::hardware_concurrency());
getchar();
auto i = 0u;
fp = fopen("tmp.tmp", "w");
fp = fopen("tmp.tmp", "wb");
auto time = chrono::high_resolution_clock::now();
while(i++ < n_jobs) tp.enqueue_task({ [](void* f) {fprintf(fp, "%d ", *(int*)f); free(f); }, new int(i) });
puts("done dispatching.");
@@ -53,7 +53,7 @@ long long testing_transaction(uint32_t n_burst, uint32_t n_batch,
}
long long testing_destruction(bool prompt = true){
fp = fopen("tmp.tmp", "w");
fp = fopen("tmp.tmp", "wb");
if (prompt) {
puts("Press any key to start.");
getchar();
+38 -22
View File
@@ -3,6 +3,9 @@
#include <cstdint>
#include <type_traits>
#include <tuple>
#include <string_view>
#include <string>
#include <utility>
using std::size_t;
#if defined(__SIZEOF_INT128__) and not defined(_WIN32)
@@ -13,6 +16,9 @@ using std::size_t;
#define __restrict__ __restrict
#endif
template<class T>
struct vector_base {};
template <class T>
constexpr static inline bool is_vector(const T&) {
return false;
@@ -32,23 +38,23 @@ struct aqis_same_impl {
std::conditional_t<
std::is_same_v<T1, bool> || std::is_same_v<T2, bool>,
std::bool_constant<std::is_same_v<T1, bool> && std::is_same_v<T2, bool>>,
Cond(
(std::is_same_v<T1, bool> && std::is_same_v<T2, bool>),
std::true_type,
std::false_type
),
Cond(
std::is_signed_v<T1> == std::is_signed_v<T2>,
Cond(
std::is_floating_point_v<T1> == std::is_floating_point_v<T2>,
Cond(
aq_szof<T1> == aq_szof<T2>, // deal with sizeof(void)
std::true_type,
std::false_type
),
std::false_type
),
std::false_type
!(std::is_class_v<T1> || std::is_class_v<T2>),
Cond(
std::is_signed_v<T1> == std::is_signed_v<T2>,
Cond(
std::is_floating_point_v<T1> == std::is_floating_point_v<T2>,
std::bool_constant<aq_szof<T1> == aq_szof<T2>>, // deal with sizeof(void)
std::false_type
),
std::false_type
),
Cond(
(std::is_class_v<T1> && std::is_class_v<T2>),
std::bool_constant<(std::is_base_of_v<T1, T2> || std::is_base_of_v<T2, T1>)>,
std::false_type
)
)
>::value;
};
@@ -63,12 +69,12 @@ constexpr bool aqis_same<T1, T2> = aqis_same_impl<T1, T2>::value;
namespace types {
enum Type_t {
AINT32, AFLOAT, ASTR, ADOUBLE, ALDOUBLE, AINT64, AINT128, AINT16, ADATE, ATIME, AINT8,
AUINT32, AUINT64, AUINT128, AUINT16, AUINT8, ABOOL, VECTOR, ATIMESTAMP, ACHAR, NONE, ERROR
AUINT32, AUINT64, AUINT128, AUINT16, AUINT8, ABOOL, VECTOR, ATIMESTAMP, ACHAR, ASV, NONE, ERROR
};
static constexpr const char* printf_str[] = { "%d", "%f", "%s", "%lf", "%Lf", "%ld", "%d", "%hi", "%s", "%s", "%hhd",
"%u", "%lu", "%s", "%hu", "%hhu", "%s", "%s", "Vector<%s>", "%s", "%c", "NULL", "ERROR" };
static constexpr const char* printf_str[] = { "%d", "%f", "%s", "%lf", "%Lf", "%ld", "%s", "%hi", "%s", "%s", "%hhd",
"%u", "%lu", "%s", "%hu", "%hhu", "%s", "Vector<%s>", "%s", "%c", "%s", "NULL", "ERROR" };
static constexpr const char* SQL_Type[] = { "INT", "REAL", "TEXT", "DOUBLE", "DOUBLE", "BIGINT", "HUGEINT", "SMALLINT", "DATE", "TIME", "TINYINT",
"INT", "BIGINT", "HUGEINT", "SMALLINT", "TINYINT", "BOOL", "HUGEINT", "TIMESTAMP", "CHAR", "NULL", "ERROR"};
"INT", "BIGINT", "HUGEINT", "SMALLINT", "TINYINT", "BOOL", "HUGEINT", "TIMESTAMP", "CHAR", "TEXT", "NULL", "ERROR"};
// TODO: deal with data/time <=> str/uint conversion
@@ -169,6 +175,8 @@ namespace types {
f(unsigned short, AUINT16) \
f(bool, ABOOL) \
f(timestamp_t, ATIMESTAMP) \
f(std::string_view, ASV) \
f(std::string, ASV) \
F_INT128(f)
inline constexpr static Type_t getType() {
@@ -399,7 +407,6 @@ struct transValues_s<lT<vT, T...>, vT, rT> {
using type = rT<T...>;
};
#include <utility>
template <class vT, int i, template <vT ...> class rT>
using transValues = typename transValues_s<std::make_integer_sequence<vT, i>, vT, rT>::type;
template <int i, template <int ...> class rT>
@@ -427,8 +434,17 @@ template <class ...T>
using get_first = typename get_first_impl<T...>::first;
template <class T>
struct value_type_rec_impl { typedef T type; };
template <template <class...> class VT, class ...V>
struct value_type_rec_impl<VT<V...>> { typedef typename value_type_rec_impl<get_first<V...>>::type type; };
struct value_type_rec_impl<VT<V...>> {
typedef typename
std::conditional_t<
std::is_base_of_v<vector_base<get_first<V...>>, VT<V...>>,
typename value_type_rec_impl<get_first<V...>>::type,
VT<V...>
> type;
};
template <class T>
using value_type_r = typename value_type_rec_impl<T>::type;
+67 -9
View File
@@ -1059,15 +1059,13 @@ public:
return do_insert_or_assign(std::move(key), std::forward<M>(mapped)).first;
}
template <class K>
unsigned hashtable_push(K&& key) {
auto it_isinserted = try_emplace(std::forward<K>(key), 1);
if (!it_isinserted.second) {
++ it_isinserted.first->second;
return static_cast<unsigned>(it_isinserted.first - begin());
}
return static_cast<unsigned>(end() - begin() - 1);
}
// template <class K>
// bool hashtable_push(K&& key) {
// auto it_isinserted = try_emplace(std::forward<K>(key), 1);
// if (!it_isinserted.second)
// ++ it_isinserted.first->second;
// return it_isinserted.second;
// }
template <typename K,
typename M,
@@ -1112,6 +1110,66 @@ public:
return {begin() + static_cast<difference_type>(value_idx), true};
}
template <class K,
typename Q = T,
typename H = Hash,
typename KE = KeyEqual>//,
//std::enable_if_t<!is_map_v<Q> && is_transparent_v<H, KE>, bool> = true>
auto hashtable_push(K&& key) -> unsigned {
if (is_full()) {
increase_size();
}
auto hash = mixed_hash(key);
auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
auto bucket_idx = bucket_idx_from_hash(hash);
while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
m_equal(key, m_values[at(m_buckets, bucket_idx).m_value_idx])) {
// found it, return without ever actually creating anything
return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
}
dist_and_fingerprint = dist_inc(dist_and_fingerprint);
bucket_idx = next(bucket_idx);
}
// value is new, insert element first, so when exception happens we are in a valid state
m_values.emplace_back(std::forward<K>(key));
// now place the bucket and shift up until we find an empty spot
auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
return static_cast<uint32_t>(value_idx);
}
// template <class... Args>
// auto hashtable_push(Args&&... args) -> unsigned {
// if (is_full()) {
// increase_size();
// }
// // we have to instantiate the value_type to be able to access the key.
// // 1. emplace_back the object so it is constructed. 2. If the key is already there, pop it later in the loop.
// auto& key = get_key(m_values.emplace_back(std::forward<Args>(args)...));
// auto hash = mixed_hash(key);
// auto dist_and_fingerprint = dist_and_fingerprint_from_hash(hash);
// auto bucket_idx = bucket_idx_from_hash(hash);
// while (dist_and_fingerprint <= at(m_buckets, bucket_idx).m_dist_and_fingerprint) {
// if (dist_and_fingerprint == at(m_buckets, bucket_idx).m_dist_and_fingerprint &&
// m_equal(key, get_key(m_values[at(m_buckets, bucket_idx).m_value_idx]))) {
// m_values.pop_back(); // value was already there, so get rid of it
// return static_cast<uint32_t>(at(m_buckets, bucket_idx).m_value_idx);
// }
// dist_and_fingerprint = dist_inc(dist_and_fingerprint);
// bucket_idx = next(bucket_idx);
// }
// // value is new, place the bucket and shift up until we find an empty spot
// auto value_idx = static_cast<value_idx_type>(m_values.size() - 1);
// place_and_shift_up({dist_and_fingerprint, value_idx}, bucket_idx);
// return static_cast<uint32_t>(value_idx);
// }
template <class... Args>
auto emplace(Args&&... args) -> std::pair<iterator, bool> {
if (is_full()) {
+121 -22
View File
@@ -17,8 +17,6 @@
#include "types.h"
#include "gc.h"
#pragma pack(push, 1)
template<class T>
struct vector_base {};
struct vectortype_cstorage{
void* container;
@@ -32,7 +30,6 @@ public:
void inline _copy(const vector_type<_Ty>& vt) {
// quick init while using malloc
//if (capacity > 0) free(container);
this->size = vt.size;
this->capacity = vt.capacity;
if (capacity) {
@@ -52,26 +49,33 @@ public:
this->container = vt.container;
// puts("move");
vt.size = vt.capacity = 0;
vt.container = 0;
vt.container = nullptr;
}
public:
_Ty* container;
uint32_t size, capacity;
typedef _Ty* iterator_t;
typedef std::conditional_t<is_cstr<_Ty>(), astring_view, _Ty> value_t;
vector_type(const uint32_t& size) : size(size), capacity(size) {
explicit vector_type(const uint32_t& size) : size(size), capacity(size) {
if (GC::scratch_space != nullptr) {
[[likely]]
container = (_Ty*)GC::scratch_space->alloc(size * sizeof(_Ty));
}
container = (_Ty*)malloc(size * sizeof(_Ty));
// TODO: calloc for objects.
}
constexpr vector_type(std::initializer_list<_Ty> _l) {
explicit constexpr vector_type(std::initializer_list<_Ty> _l) {
size = capacity = _l.size();
_Ty* _container = this->container = (_Ty*)malloc(sizeof(_Ty) * _l.size());
this->container = (_Ty*)malloc(sizeof(_Ty) * capacity);
_Ty* _container = this->container;
for (const auto& l : _l) {
*(_container++) = l;
}
}
constexpr vector_type() noexcept : size(0), capacity(0), container(0) {};
constexpr vector_type(_Ty* container, uint32_t len) noexcept : size(len), capacity(0), container(container) {};
constexpr vector_type(const char** container, uint32_t len,
typename std::enable_if_t<!std::is_same_v<_Ty, const char*>>* = nullptr) noexcept = delete;
constexpr explicit vector_type(const vector_type<_Ty>& vt) noexcept : capacity(0) {
_copy(vt);
}
@@ -81,8 +85,9 @@ public:
constexpr vector_type(vector_type<_Ty>&& vt) noexcept : capacity(0) {
_move(std::move(vt));
}
vector_type(vectortype_cstorage vt) noexcept : capacity(vt.capacity), size(vt.size), container((_Ty*)vt.container) {
out(10);
explicit vector_type(vectortype_cstorage vt) noexcept :
capacity(vt.capacity), size(vt.size), container((_Ty*)vt.container) {
// out(10);
};
// size >= capacity ==> readonly vector
constexpr vector_type(const uint32_t size, void* data) :
@@ -188,15 +193,15 @@ public:
grow<false>(sz);
}
void emplace_back(const _Ty& _val) {
inline void emplace_back(const _Ty& _val) {
grow();
container[size++] = _val;
}
void emplace_back(_Ty& _val) {
inline void emplace_back(_Ty& _val) {
grow();
container[size++] = std::move(_val);
}
void emplace_back(_Ty&& _val) {
inline void emplace_back(_Ty&& _val) {
grow();
container[size++] = std::move(_val);
}
@@ -213,10 +218,10 @@ public:
return _it;
}
iterator_t begin() const {
inline iterator_t begin() const {
return container;
}
iterator_t end() const {
inline iterator_t end() const {
return container + size;
}
@@ -230,7 +235,7 @@ public:
return container[_i];
}
void shrink_to_fit() {
inline void shrink_to_fit() {
if (size && capacity != size) {
capacity = size;
_Ty* _container = (_Ty*)malloc(sizeof(_Ty) * size);
@@ -240,13 +245,17 @@ public:
}
}
_Ty& back() {
inline void clear() {
this->size = 0;
}
inline _Ty& back() {
return container[size - 1];
}
void qpop() {
inline void qpop() {
size = size ? size - 1 : size;
}
void pop_resize() {
inline void pop_resize() {
if (size) {
--size;
if (capacity > (size << 1))
@@ -259,7 +268,7 @@ public:
}
}
}
_Ty pop() {
inline _Ty pop() {
return container[--size];
}
void merge(vector_type<_Ty>& _other) {
@@ -331,7 +340,7 @@ public:
inline vector_type<_Ty> subvec_deep(uint32_t start = 0) const { return subvec_deep(start, size); }
vector_type<_Ty> getRef() { return vector_type<_Ty>(container, size); }
~vector_type() {
if (capacity > 0);// GC::gc_handle->reg(container, sizeof(_Ty) * capacity);//free(container);
if (capacity > 0) GC::gc_handle->reg(container, sizeof(_Ty) * capacity);//free(container);
container = 0; size = capacity = 0;
}
#define Compare(_op) \
@@ -369,7 +378,7 @@ public:
#define Ops(o, x) \
template<typename T>\
vector_type<typename types::Coercion<_Ty, T>::type> operator o (const vector_type<T>& r) const {\
/*[[likely]] if (r.size == size) {*/\
/*if (r.size == size) { [[likely]] */\
return x(r);\
/*}*/\
}
@@ -377,7 +386,7 @@ public:
#define Opseq(o, x) \
template<typename T>\
vector_type<typename types::Coercion<_Ty, T>::type> operator o##= (const vector_type<T>& r) {\
/*[[likely]] if (r.size == size) {*/\
/*if (r.size == size) { [[likely]] */\
return x##eq(r);\
/*}*/\
}
@@ -395,6 +404,52 @@ public:
_Make_Ops(Opseq)
};
template <>
constexpr vector_type<std::string_view>::vector_type(const char** container, uint32_t len,
typename std::enable_if_t<true>*) noexcept
{
size = capacity = len;
this->container = static_cast<std::string_view*>(
malloc(sizeof(std::string_view) * len));
for(uint32_t i = 0; i < len; ++i){
this->container[i] = container[i];
}
}
template<>
constexpr vector_type<std::string_view>::vector_type(const uint32_t size, void* data) :
size(size), capacity(0) {
this->container = static_cast<std::string_view*>(
malloc(sizeof(std::string_view) * size));
for(uint32_t i = 0; i < size; ++i){
this->container[i] = ((const char**)data)[i];
}
//std::cout<<size << container[1];
}
// template<>
// void vector_type<std::string_view>::init_from(const uint32_t size, void* data) {
// this->size = this->capacity = size;
// this->container = static_cast<std::string_view*>(
// malloc(sizeof(std::string_view) * size));
// for(uint32_t i = 0; i < size; ++i){
// this->container[i] = container[i];
// }
// }
// template<template <typename> class VT>
// inline void
// prealloc_vector (VT &vt, uint32_t sz) {
// vt.reserve(sz);
// }
// template<class T>
// inline void
// prealloc_vector (vector_type<vector_type<T>> &vt,
// uint32_t outer_sz, uint32_t inner_sz) {
// vt.reserve(outer_sz);
// auto mem = static_cast<T*>(malloc(inner_sz * sizeof(T)));
// }
template <>
class vector_type<void> {
@@ -428,4 +483,48 @@ public:
vector_type<void> subvec_deep(uint32_t);
};
#pragma pack(pop)
template <class Key, class Hash>
class AQHashTable : public ankerl::unordered_dense::set<Key, Hash> {
public:
uint32_t* reversemap, *mapbase, *ht_base;
AQHashTable() = default;
explicit AQHashTable(uint32_t sz)
: ankerl::unordered_dense::set<Key, Hash>{} {
this->reserve(sz);
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
mapbase = reversemap + sz;
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
}
void init(uint32_t sz) {
ankerl::unordered_dense::set<Key, Hash>::reserve(sz);
reversemap = static_cast<uint32_t *>(malloc(sizeof(uint32_t) * sz * 2));
mapbase = reversemap + sz;
ht_base = static_cast<uint32_t *>(calloc(sz, sizeof(uint32_t)));
}
inline void hashtable_push(Key&& k, uint32_t i){
reversemap[i] = ankerl::unordered_dense::set<Key, Hash>::hashtable_push(std::move(k));
++ht_base[reversemap[i]];
}
auto ht_postproc(uint32_t sz) {
auto& arr_values = this->values();
const auto& len = this->size();
auto vecs = static_cast<vector_type<uint32_t>*>(malloc(sizeof(vector_type<uint32_t>) * len));
vecs[0].init_from(ht_base[0], mapbase);
for (uint32_t i = 1; i < len; ++i) {
vecs[i].init_from(ht_base[i], mapbase + ht_base[i - 1]);
ht_base[i] += ht_base[i - 1];
}
for (uint32_t i = 0; i < sz; ++i) {
auto id = reversemap[i];
mapbase[--ht_base[id]] = i;
}
return vecs;
}
};
#endif