Finite-state machine example.
using zth::operator""_s;
namespace fsm {
static void init_()
{
printf("\x1b[0m ________ \n");
printf("/ \\\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("\\________/\n");
printf(" || \n");
printf(" || \n");
printf(" || \n");
printf(" || \n");
printf("\nPress enter to generate traffic.\n");
printf("\x1b[17A\x1b[s");
}
static void off_()
{
printf("\n\x1b[u");
printf(" ________ \n");
printf("/ \\\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("\\________/\n");
printf("\n\x1b[11A");
(void)fflush(nullptr);
}
static void red_()
{
printf("\n\x1b[u");
printf(" ________ \n");
printf("/ \\\n");
printf("| \x1b[31;1m00\x1b[0m |\n");
printf("| \x1b[31;1m00\x1b[0m |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("\\________/\n");
printf("\n\x1b[11A");
(void)fflush(nullptr);
}
static void amber_()
{
printf("\n\x1b[u");
printf(" ________ \n");
printf("/ \\\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| \x1b[33m00\x1b[0m |\n");
printf("| \x1b[33m00\x1b[0m |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("\\________/\n");
printf("\n\x1b[11A");
(void)fflush(nullptr);
}
static void green_()
{
printf("\n\x1b[u");
printf(" ________ \n");
printf("/ \\\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| .. |\n");
printf("| .. |\n");
printf("| |\n");
printf("| \x1b[32;1m00\x1b[0m |\n");
printf("| \x1b[32;1m00\x1b[0m |\n");
printf("\\________/\n");
printf("\n\x1b[11A");
(void)fflush(nullptr);
}
constexpr auto init = action(init_, "init");
constexpr auto off = action(off_, "off");
constexpr auto red = action(red_, "red");
constexpr auto amber = action(amber_, "amber");
#if __cplusplus < 201703L
constexpr auto green = action(green_, "green");
#else
constexpr auto green = action([]() { green_(); }, "green");
#endif
class TrafficLight :
public Fsm {
public:
void justGotGreen()
{
m_green = t();
}
auto tooLongGreen() const
{
}
private:
};
constexpr auto justGotGreen = action(&TrafficLight::justGotGreen, "justGotGreen");
constexpr auto tooLongGreen = guard(&TrafficLight::tooLongGreen, "tooLongGreen");
constexpr auto transitions = compile(
"init" / init >>= "blink on",
"blink on" + entry / amber ,
+ timeout_s<1> >>= "blink off",
"blink off" + entry / off ,
+ timeout_s<1> >>= "peek",
"peek" + input("traffic") >>= "amber",
+ always >>= "blink on",
"red (wait)" + entry / red ,
+ timeout_s<2> >>= "red",
"red" + input("traffic") / consume >>= "green (first)",
+ timeout_s<10> >>= "blink off",
"green (first)" / justGotGreen >>= "green",
"green" + entry / green ,
+ tooLongGreen >>= "amber",
+ input("traffic") / consume >>= "green",
+ timeout_s<3> >>= "amber",
"amber" + entry / amber ,
+ timeout_s<2> >>= "red (wait)"
);
}
static void trafficDetect(fsm::TrafficLight& fsm)
{
char buf = 0;
fsm.input("traffic");
}
{
fsm::transitions.dump();
(void)fflush(stdout);
fsm::transitions.uml(stderr);
(void)fflush(stderr);
fsm::TrafficLight fsm;
fsm::transitions.init(fsm);
fsm.run();
return 0;
}
Convenient wrapper around struct timespec that contains an absolute timestamp.
int main_fiber(int argc, char **argv)
#define zth_config(name)
Checks if the given zth::Config field is enabled.
fiber_type< F >::fiber fiber(F &&f, Args &&... args)
Create and start a new fiber.
ssize_t read(int fd, void *buf, size_t count)
Like normal read(), but forwards the poll() to the zth::Waiter in case it would block.