state context works

lib
Avril 4 years ago
parent 5346b0127e
commit 6fbd197e57
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -9,10 +9,12 @@ inline T* _sm_var(sm_state* state, U name, T init)
{ {
auto val = &state->current->user.data[name]; auto val = &state->current->user.data[name];
bool set = val->set; bool set = val->set;
val->set = true; val->set = true;
val->free = false;
return ( ! set ) ? return ( ! set ) ?
_sm_init<T>(val, init) : (val->free = false, _sm_init<T>(val, init)) :
_sm_get<T>(val); _sm_get<T>(val);
} }
template<uint64_t name, typename T> template<uint64_t name, typename T>
@ -43,3 +45,5 @@ inline sm_yield sm_continue() { return (sm_yield)_sm_noop; }
#define SM_YIELD(v) do { state->current->pc = __LINE__; return (sm_yield)(v); case __LINE__:; } while(0) #define SM_YIELD(v) do { state->current->pc = __LINE__; return (sm_yield)(v); case __LINE__:; } while(0)
sm_state* sm_new();
void sm_free(sm_state* state);

@ -4,6 +4,8 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <cstdio> #include <cstdio>
#define restrict __restrict__
[[noreturn]] [[noreturn]]
#else #else
#include <stdio.h> #include <stdio.h>

@ -5,7 +5,6 @@
#define BODY(T, U, nm) \ #define BODY(T, U, nm) \
template<> T* _sm_init<T>(_sm_user* frame, T init) \ template<> T* _sm_init<T>(_sm_user* frame, T init) \
{ \ { \
printf("hi\n"); \
frame->free = false; \ frame->free = false; \
frame-> nm = (U)init; \ frame-> nm = (U)init; \
return (T*)&frame-> nm; \ return (T*)&frame-> nm; \

@ -16,21 +16,32 @@ sm_yield sm_test(sm_state* state)
*d = 10.f; *d = 10.f;
SM_BEGIN; SM_BEGIN;
SM_YIELD(sm_continue());
*a = 5; *a = 5;
SM_YIELD(sm_continue()); SM_YIELD(sm_continue());
printf("a = %d\n", *a);
*a = 0; *a = 0;
SM_YIELD(sm_continue());
printf("a = %d\n", *a);
SM_END; SM_END;
} }
int main() int main()
{ {
auto state = sm_new();
sm_test(state);
sm_test(state);
sm_test(state);
sm_free(state);
/*
//TODO: `sm_state` creation/initialisation & freeing functions //TODO: `sm_state` creation/initialisation & freeing functions
//TODO: Test `sm_test` //TODO: Test `sm_test`
_test hi = { 0, 0 }; _test hi = { 0, 0 };
auto _a = _sm_init(nullptr, hi); auto _a = _sm_init(nullptr, hi);
*/
return 0; return 0;
} }

@ -1,13 +1,64 @@
#include <state.h> #include <state.h>
#include "dev.h" #include "dev.h"
void _sm_pop_stack(sm_state* state) /// A generator that just returns `nullptr` (end). Used for yielding without calling in to another generator.
///
/// NOTE: To avoid uselessly creating a stack frame for calls to this generator, its address is (TODO) directly compared to when switching into a deeper generator, and then skipped entirely.
sm_yield _sm_noop(sm_state*)
{ {
TODO("Free the current stack frame in `state` and replace it with the previous one"); return (sm_yield)nullptr;
} }
sm_yield _sm_noop(sm_state*) sm_state* sm_new()
{ {
return (sm_yield)nullptr; auto state = box<sm_state>();
state->current = box<_sm_frame, true>();
return state;
} }
inline static void sm_free_user(_sm_user* data)
{
if (data->free) {
free(data->_ptr);
}
}
inline static void _sm_free_page(_sm_user_page* page)
{
for (int i=0;i<_SM_STACK_SIZE;i++) sm_free_user(&page->data[i]);
}
inline static void _sm_free_all_pages(_sm_user_page* page)
{
while(page)
{
_sm_free_page(page);
auto old = page;
page = page->next;
free(old);
}
}
void sm_free(sm_state* state)
{
_sm_frame* frame = unbox(state).current;
while(frame)
{
_sm_free_all_pages(frame->user.next);
_sm_free_page(&frame->user);
frame = unbox(frame).prev;
}
}
void _sm_pop_stack(sm_state* state)
{
if(!state->current) return;
auto last = unbox(state->current);
state->current = last.prev;
_sm_free_all_pages(last.user.next);
_sm_free_page(&last.user);
}

Loading…
Cancel
Save