triggers
This commit is contained in:
+6
-1
@@ -7,6 +7,12 @@
|
||||
#include "types.h"
|
||||
// #include "robin_hood.h"
|
||||
#include "unordered_dense.h"
|
||||
template<typename Key, typename Val>
|
||||
using aq_map = ankerl::unordered_dense::map<Key, Val>;
|
||||
|
||||
template<typename Key>
|
||||
using aq_set = ankerl::unordered_dense::set<Key>;
|
||||
|
||||
// only works for 64 bit systems
|
||||
namespace hasher_consts{
|
||||
constexpr size_t _FNV_offset_basis = 14695981039346656037ULL;
|
||||
@@ -19,7 +25,6 @@ inline size_t append_bytes(const unsigned char* _First) noexcept {
|
||||
_Val ^= static_cast<size_t>(*_First);
|
||||
_Val *= hasher_consts::_FNV_prime;
|
||||
}
|
||||
|
||||
return _Val;
|
||||
}
|
||||
|
||||
|
||||
@@ -58,27 +58,6 @@ void print<bool>(const bool&v, const char* delimiter){
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
T getInt(const char*& buf){
|
||||
T ret = 0;
|
||||
while(*buf >= '0' and *buf <= '9'){
|
||||
ret = ret*10 + *buf - '0';
|
||||
buf++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
char* intToString(T val, char* buf){
|
||||
|
||||
while (val > 0){
|
||||
*--buf = val%10 + '0';
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void skip(const char*& buf){
|
||||
while(*buf && (*buf >'9' || *buf < '0')) buf++;
|
||||
}
|
||||
|
||||
+35
-1
@@ -9,6 +9,7 @@
|
||||
#include <unordered_map>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <cstring>
|
||||
class aq_timer {
|
||||
private:
|
||||
std::chrono::high_resolution_clock::time_point now;
|
||||
@@ -32,6 +33,27 @@ public:
|
||||
|
||||
#include "table.h"
|
||||
|
||||
template<class T = int>
|
||||
T getInt(const char*& buf){
|
||||
T ret = 0;
|
||||
while(*buf >= '0' and *buf <= '9'){
|
||||
ret = ret*10 + *buf - '0';
|
||||
buf++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
char* intToString(T val, char* buf){
|
||||
|
||||
while (val > 0){
|
||||
*--buf = val%10 + '0';
|
||||
val /= 10;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
enum Log_level {
|
||||
LOG_INFO,
|
||||
@@ -72,7 +94,9 @@ struct StoredProcedure {
|
||||
const char* name;
|
||||
void **__rt_loaded_modules;
|
||||
};
|
||||
|
||||
struct Trigger;
|
||||
struct IntervalBasedTriggerHost;
|
||||
struct CallbackBasedTriggerHost;
|
||||
|
||||
struct Context {
|
||||
typedef int (*printf_type) (const char *format, ...);
|
||||
@@ -113,6 +137,9 @@ struct Context {
|
||||
std::unordered_map<std::string, void*> tables;
|
||||
std::unordered_map<std::string, uColRef *> cols;
|
||||
std::unordered_map<std::string, StoredProcedure> stored_proc;
|
||||
std::unordered_map<std::string, Trigger> triggers;
|
||||
IntervalBasedTriggerHost *it_host;
|
||||
CallbackBasedTriggerHost *ct_host;
|
||||
};
|
||||
|
||||
|
||||
@@ -176,6 +203,13 @@ inline void AQ_ZeroMemory(_This_Struct& __val) {
|
||||
memset(&__val, 0, sizeof(_This_Struct));
|
||||
}
|
||||
|
||||
template <typename _This_Type>
|
||||
inline _This_Type* AQ_DupObject(_This_Type* __val) {
|
||||
auto ret = (_This_Type*)(malloc(sizeof(_This_Type)));
|
||||
memcpy(ret, __val, sizeof(_This_Type));
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef __USE_STD_SEMAPHORE__
|
||||
#include <semaphore>
|
||||
class A_Semaphore {
|
||||
|
||||
+34
-1
@@ -559,6 +559,37 @@ start:
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'T': // triggers
|
||||
{
|
||||
switch(n_recvd[i][1]){
|
||||
case 'I': // register interval based trigger
|
||||
{
|
||||
const char* action_name = n_recvd[i] + 2;
|
||||
while(*action_name++);
|
||||
if(auto p = get_procedure(cxt, action_name); p.name == nullptr)
|
||||
printf("Invalid action name: %s\n", action_name);
|
||||
else {
|
||||
auto action = AQ_DupObject(&p);
|
||||
const char* interval = action_name;
|
||||
while(*interval++);
|
||||
const auto i_interval = getInt<uint32_t>(interval);
|
||||
cxt->it_host->add_trigger(n_recvd[i] + 2, action, i_interval);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'C': // activate callback based trigger
|
||||
break;
|
||||
case 'R': // remove trigger
|
||||
{
|
||||
cxt->it_host->remove_trigger(n_recvd[i] + 2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("Corrupted message from prompt: %s\n", n_recvd[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -618,7 +649,7 @@ int launcher(int argc, char** argv){
|
||||
str = std::string("cd ") + pwd + std::string("&& python3 ./prompt.py ") + str;
|
||||
return system(str.c_str());
|
||||
}
|
||||
#if !defined(TESTMAIN) && !( defined(_MSC_VER) && defined(_DEBUG) )
|
||||
#if true || !defined(TESTMAIN) && !( defined(_MSC_VER) && defined(_DEBUG) )
|
||||
extern "C" int __DLLEXPORT__ main(int argc, char** argv) {
|
||||
#ifdef __AQ_BUILD_LAUNCHER__
|
||||
return launcher(argc, argv);
|
||||
@@ -631,6 +662,8 @@ extern "C" int __DLLEXPORT__ main(int argc, char** argv) {
|
||||
#ifdef THREADING
|
||||
auto tp = new ThreadPool();
|
||||
cxt->thread_pool = tp;
|
||||
cxt->it_host = new IntervalBasedTriggerHost(tp);
|
||||
cxt->ct_host = new CallbackBasedTriggerHost(tp);
|
||||
#endif
|
||||
|
||||
const char* shmname;
|
||||
|
||||
+18
-6
@@ -156,16 +156,17 @@ bool ThreadPool::busy(){
|
||||
|
||||
IntervalBasedTriggerHost::IntervalBasedTriggerHost(ThreadPool* tp){
|
||||
this->tp = tp;
|
||||
this->triggers = new vector_type<IntervalBasedTrigger>;
|
||||
this->triggers = new aq_map<std::string, IntervalBasedTrigger>;
|
||||
trigger_queue_lock = new mutex();
|
||||
this->now = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||
}
|
||||
|
||||
void IntervalBasedTriggerHost::add_trigger(StoredProcedure *p, uint32_t interval) {
|
||||
void IntervalBasedTriggerHost::add_trigger(const char* name, StoredProcedure *p, uint32_t interval) {
|
||||
auto tr = IntervalBasedTrigger{.interval = interval, .time_remaining = 0, .sp = p};
|
||||
auto vt_triggers = static_cast<vector_type<IntervalBasedTrigger> *>(this->triggers);
|
||||
auto vt_triggers = static_cast<aq_map<std::string, IntervalBasedTrigger> *>(this->triggers);
|
||||
trigger_queue_lock->lock();
|
||||
vt_triggers->emplace_back(tr);
|
||||
vt_triggers->emplace(name, tr);
|
||||
//(*vt_triggers)[name] = tr;
|
||||
trigger_queue_lock->unlock();
|
||||
}
|
||||
|
||||
@@ -173,9 +174,9 @@ void IntervalBasedTriggerHost::tick() {
|
||||
const auto current_time = std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||
const auto delta_t = static_cast<uint32_t>((current_time - now) / 1000000); // miliseconds precision
|
||||
now = current_time;
|
||||
auto vt_triggers = static_cast<vector_type<IntervalBasedTrigger> *>(this->triggers);
|
||||
auto vt_triggers = static_cast<aq_map<std::string, IntervalBasedTrigger> *>(this->triggers);
|
||||
trigger_queue_lock->lock();
|
||||
for(auto& t : *vt_triggers) {
|
||||
for(auto& [_, t] : vt_triggers->values()) {
|
||||
if(t.tick(delta_t)) {
|
||||
payload_t payload;
|
||||
payload.f = execTriggerPayload;
|
||||
@@ -187,6 +188,11 @@ void IntervalBasedTriggerHost::tick() {
|
||||
trigger_queue_lock->unlock();
|
||||
}
|
||||
|
||||
void IntervalBasedTriggerHost::remove_trigger(const char* name) {
|
||||
auto vt_triggers = static_cast<aq_map<std::string, IntervalBasedTrigger> *>(this->triggers);
|
||||
vt_triggers->erase(name);
|
||||
}
|
||||
|
||||
void IntervalBasedTrigger::reset() {
|
||||
time_remaining = interval;
|
||||
}
|
||||
@@ -201,3 +207,9 @@ bool IntervalBasedTrigger::tick(uint32_t delta_t) {
|
||||
time_remaining = time_remaining - curr_dt;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CallbackBasedTriggerHost::CallbackBasedTriggerHost(ThreadPool *tp) {
|
||||
this->tp = tp;
|
||||
}
|
||||
|
||||
void CallbackBasedTriggerHost::tick() {}
|
||||
+10
-7
@@ -2,6 +2,8 @@
|
||||
#define _AQ_THREADING_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
typedef int(*payload_fn_t)(void*);
|
||||
struct payload_t{
|
||||
@@ -39,12 +41,11 @@ private:
|
||||
|
||||
};
|
||||
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
class A_Semphore;
|
||||
|
||||
class TriggerHost {
|
||||
protected:
|
||||
public:
|
||||
void* triggers;
|
||||
std::thread* handle;
|
||||
ThreadPool *tp;
|
||||
@@ -52,14 +53,15 @@ protected:
|
||||
std::mutex* trigger_queue_lock;
|
||||
|
||||
virtual void tick() = 0;
|
||||
public:
|
||||
TriggerHost() = default;
|
||||
virtual ~TriggerHost() = default;
|
||||
};
|
||||
|
||||
struct StoredProcedure;
|
||||
|
||||
struct IntervalBasedTrigger {
|
||||
struct Trigger{};
|
||||
|
||||
struct IntervalBasedTrigger : Trigger {
|
||||
uint32_t interval; // in milliseconds
|
||||
uint32_t time_remaining;
|
||||
StoredProcedure* sp;
|
||||
@@ -70,8 +72,8 @@ struct IntervalBasedTrigger {
|
||||
class IntervalBasedTriggerHost : public TriggerHost {
|
||||
public:
|
||||
explicit IntervalBasedTriggerHost(ThreadPool *tp);
|
||||
void add_trigger(StoredProcedure* stored_procedure, uint32_t interval);
|
||||
void remove_trigger(uint32_t tid);
|
||||
void add_trigger(const char* name, StoredProcedure* stored_procedure, uint32_t interval);
|
||||
void remove_trigger(const char* name);
|
||||
private:
|
||||
unsigned long long now;
|
||||
void tick() override;
|
||||
@@ -79,6 +81,7 @@ private:
|
||||
|
||||
class CallbackBasedTriggerHost : public TriggerHost {
|
||||
public:
|
||||
explicit CallbackBasedTriggerHost(ThreadPool *tp);
|
||||
void add_trigger();
|
||||
private:
|
||||
void tick() override;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "gc.h"
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct vectortype_cstorage{
|
||||
struct vectortype_cstorage {
|
||||
void* container;
|
||||
unsigned int size, capacity;
|
||||
};
|
||||
@@ -123,7 +123,7 @@ public:
|
||||
_copy(vt);
|
||||
return *this;
|
||||
}
|
||||
vector_type<_Ty>& operator =(vector_type<_Ty>&& vt) {
|
||||
vector_type<_Ty>& operator =(vector_type<_Ty>&& vt) noexcept {
|
||||
_move(std::move(vt));
|
||||
return *this;
|
||||
}
|
||||
@@ -139,10 +139,10 @@ public:
|
||||
|
||||
return *this;
|
||||
}
|
||||
inline std::unordered_set<value_t> distinct_common(){
|
||||
inline std::unordered_set<value_t> distinct_common() {
|
||||
return std::unordered_set<value_t>(container, container + size);
|
||||
}
|
||||
vector_type<_Ty>& distinct_inplace(){
|
||||
vector_type<_Ty>& distinct_inplace() {
|
||||
uint32_t i = 0;
|
||||
for(const auto& v : distinct_common()){
|
||||
container[i++] = v;
|
||||
|
||||
Reference in New Issue
Block a user