Add fiber interface
This commit is contained in:
parent
f4e4ef353a
commit
b138f99f4c
164
include/mtl/fiber.hpp
Normal file
164
include/mtl/fiber.hpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_ACTIVE
|
||||||
|
#define MTL_FIBER_MAX_ACTIVE 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_QUEUE
|
||||||
|
#define MTL_FIBER_MAX_QUEUE 256
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_QUEUE_LOW
|
||||||
|
#define MTL_FIBER_MAX_QUEUE_LOW MTL_FIBER_MAX_QUEUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_QUEUE_MED
|
||||||
|
#define MTL_FIBER_MAX_QUEUE_MED MTL_FIBER_MAX_QUEUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_QUEUE_HI
|
||||||
|
#define MTL_FIBER_MAX_QUEUE_HI MTL_FIBER_MAX_QUEUE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_STACK_SIZE
|
||||||
|
#define MTL_FIBER_STACK_SIZE 4096
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MTL_FIBER_MAX_DEPENDENTS
|
||||||
|
#define MTL_FIBER_MAX_DEPENDENTS 8
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" void mtl_yield();
|
||||||
|
|
||||||
|
namespace mtl {
|
||||||
|
|
||||||
|
constexpr auto yield = mtl_yield;
|
||||||
|
|
||||||
|
// TEMPORARY
|
||||||
|
template <typename T, size_t N>
|
||||||
|
class vector {
|
||||||
|
public:
|
||||||
|
void push_back(T x) {}
|
||||||
|
|
||||||
|
T* begin() {return nullptr;}
|
||||||
|
T* end() { return nullptr;}
|
||||||
|
void clear();
|
||||||
|
constexpr size_t capacity() { return N; }
|
||||||
|
size_t size() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
using fiber_stack = uint8_t[MTL_FIBER_STACK_SIZE];
|
||||||
|
|
||||||
|
class ifiber;
|
||||||
|
|
||||||
|
class ifiber_dependency {
|
||||||
|
protected:
|
||||||
|
mtl::vector<ifiber*, MTL_FIBER_MAX_DEPENDENTS> m_dependents;
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add_dependent(ifiber* dependent);
|
||||||
|
};
|
||||||
|
|
||||||
|
class fiber_trigger;
|
||||||
|
|
||||||
|
extern ifiber* this_fiber;
|
||||||
|
|
||||||
|
class ifiber : public ifiber_dependency {
|
||||||
|
public:
|
||||||
|
enum class priority {
|
||||||
|
low,
|
||||||
|
med,
|
||||||
|
hi,
|
||||||
|
};
|
||||||
|
|
||||||
|
protected:
|
||||||
|
friend class ifiber_dependency;
|
||||||
|
|
||||||
|
static mtl::vector<ifiber*, MTL_FIBER_MAX_QUEUE_LOW> s_queue_low;
|
||||||
|
static mtl::vector<ifiber*, MTL_FIBER_MAX_QUEUE_MED> s_queue_med;
|
||||||
|
static mtl::vector<ifiber*, MTL_FIBER_MAX_QUEUE_HI> s_queue_hi;
|
||||||
|
|
||||||
|
bool m_finished;
|
||||||
|
priority m_priority;
|
||||||
|
uint32_t m_dependencies;
|
||||||
|
|
||||||
|
ifiber(priority priority) : m_priority(priority), m_finished(false), m_dependencies(0) {
|
||||||
|
switch (priority) {
|
||||||
|
case priority::low:
|
||||||
|
// If the queue is already full, a currently running
|
||||||
|
// fiber must finish first to free room in the queue.
|
||||||
|
// If all currently running fibers are waiting for a
|
||||||
|
// dependency, we will throw an exception.
|
||||||
|
if (s_queue_low.size() == s_queue_low.capacity()) {
|
||||||
|
mtl::yield();
|
||||||
|
}
|
||||||
|
s_queue_low.push_back(this);
|
||||||
|
break;
|
||||||
|
case priority::med:
|
||||||
|
if (s_queue_med.size() == s_queue_med.capacity()) {
|
||||||
|
mtl::yield();
|
||||||
|
}
|
||||||
|
s_queue_med.push_back(this);
|
||||||
|
break;
|
||||||
|
case priority::hi:
|
||||||
|
if (s_queue_hi.size() == s_queue_hi.capacity()) {
|
||||||
|
mtl::yield();
|
||||||
|
}
|
||||||
|
s_queue_hi.push_back(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
};
|
||||||
|
|
||||||
|
class fiber_trigger : public ifiber_dependency {
|
||||||
|
public:
|
||||||
|
void trigger() {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename RetType, typename... ArgTypes>
|
||||||
|
class fiber : public ifiber {
|
||||||
|
public:
|
||||||
|
using FuncType = RetType(*)(ArgTypes...);
|
||||||
|
|
||||||
|
private:
|
||||||
|
FuncType m_func;
|
||||||
|
std::tuple<ArgTypes...> m_args;
|
||||||
|
|
||||||
|
public:
|
||||||
|
fiber(FuncType func, ArgTypes... args)
|
||||||
|
: ifiber(priority::med), m_func(func), m_args(args...) {}
|
||||||
|
|
||||||
|
fiber(FuncType func, ArgTypes... args, priority priority)
|
||||||
|
: ifiber(priority), m_func(func), m_args(args...) {}
|
||||||
|
|
||||||
|
// TODO: Add priority+dependency constructors
|
||||||
|
|
||||||
|
fiber(FuncType func, ArgTypes... args, const ifiber_dependency& dep)
|
||||||
|
: ifiber(priority::med), m_func(func), m_args(args...) {
|
||||||
|
dep.add_dependent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename It>
|
||||||
|
fiber(FuncType func, ArgTypes... args, It begin, It end)
|
||||||
|
: ifiber(priority::med), m_func(func), m_args(args...) {
|
||||||
|
for (; begin != end; ++begin) {
|
||||||
|
begin->add_dependent(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void join() {
|
||||||
|
this_fiber->add_dependent(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mtl
|
||||||
Loading…
x
Reference in New Issue
Block a user