Skip to content

Commit

Permalink
actually run only once
Browse files Browse the repository at this point in the history
check stop condition after wait, grab the token value
another todo might be a proper watchdog... or running apps via
`timeout 30s <CMD>` or similar
  • Loading branch information
mcspr committed Apr 10, 2024
1 parent 750ce7a commit 36386f8
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 30 deletions.
5 changes: 3 additions & 2 deletions tests/host/common/ArduinoMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
#define MOCK_PORT_SHIFTER 9000

bool user_exit = false;
bool run_once = false;
const char* host_interface = nullptr;
size_t spiffs_kb = 1024;
size_t littlefs_kb = 1024;
Expand Down Expand Up @@ -247,6 +246,8 @@ void control_c(int sig)
int main(int argc, char* const argv[])
{
auto interval = std::chrono::milliseconds { 1 };
auto run_once = false;

blocking_uart = false; // global

signal(SIGINT, control_c);
Expand Down Expand Up @@ -345,7 +346,7 @@ int main(int argc, char* const argv[])
millis();

// loops until exit, switching between sys and user tasks
mock_loop_task(mock_system_loop, interval, user_exit);
mock_loop_task(mock_system_loop, interval, run_once, user_exit);

return 0;
}
90 changes: 63 additions & 27 deletions tests/host/common/MockTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <mutex>
#include <thread>
#include <functional>
#include <exception>

namespace
{
Expand All @@ -54,15 +55,21 @@ namespace
// - when loop() is ready to yield via esp_suspend() (either at the end of the func, or via yield()),
// notify the second thread token cv to repeat the conditions above

std::thread user_task;

std::atomic<bool> user_task_is_done { false };
std::thread user_task;
std::atomic<bool> scheduled { false };

struct StopException: public std::exception
{
const char* what() const noexcept(true) override
{
return "Stopped";
}
};

enum class Token
{
Default,
Exit,
Stop,
User,
Sys,
};
Expand All @@ -82,38 +89,62 @@ void arrive(Barrier& b, Token token)
b.cv.notify_all();
}

void wait(Barrier& b, Token token)
Token wait(Barrier& b, Token token)
{
std::unique_lock lock { b.m };
b.cv.wait(lock,
[&]()
{
return b.token == Token::Exit || b.token == token;
});

Token current;
for (;;)
{
current = b.token;
if ((current == token) || (current == Token::Stop))
{
break;
}

b.cv.wait(lock);
}

return current;
}

bool wait_or_stop(Barrier& b, Token token)
{
return Token::Stop == wait(b, token);
}

ETSTimer delay_timer;

void mock_task_wrapper()
void mock_task_wrapper(bool once)
{
std::once_flag setup_done;

for (;;)
try
{
wait(barrier, Token::User);
for (;;)
{
if (wait_or_stop(barrier, Token::User))
{
break;
}

std::call_once(setup_done, setup);
loop();
loop_end();
std::call_once(setup_done, setup);
loop();
loop_end();

esp_schedule();
arrive(barrier, Token::Sys);
if (once)
{
arrive(barrier, Token::Stop);
break;
}

if (user_task_is_done)
{
break;
esp_schedule();
arrive(barrier, Token::Sys);
}
}
catch (const StopException&)
{
}
}

} // namespace
Expand All @@ -126,7 +157,10 @@ extern "C" bool can_yield()
extern "C" void esp_suspend()
{
arrive(barrier, Token::Sys);
wait(barrier, Token::User);
if (wait_or_stop(barrier, Token::User))
{
throw StopException {};
}
}

extern "C" void esp_schedule()
Expand Down Expand Up @@ -167,14 +201,13 @@ extern "C" void esp_delay(unsigned long ms)

void mock_stop_task()
{
user_task_is_done = true;
arrive(barrier, Token::Exit);
arrive(barrier, Token::Stop);
}

void mock_loop_task(void (*system_task)(), std::chrono::milliseconds interval,
void mock_loop_task(void (*system_task)(), std::chrono::milliseconds interval, bool once,
const bool& user_exit)
{
user_task = std::thread(mock_task_wrapper);
user_task = std::thread(mock_task_wrapper, once);

esp_schedule();
for (;;)
Expand All @@ -189,7 +222,10 @@ void mock_loop_task(void (*system_task)(), std::chrono::milliseconds interval,
{
scheduled = false;
arrive(barrier, Token::User);
wait(barrier, Token::Sys);
if (wait_or_stop(barrier, Token::Sys))
{
break;
}
}

if (user_exit)
Expand Down
3 changes: 2 additions & 1 deletion tests/host/common/mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ void mock_stop_littlefs();
#ifdef __cplusplus
#include <chrono>
void mock_stop_task();
void mock_loop_task(void (*)(), std::chrono::milliseconds interval, const bool& user_exit);
void mock_loop_task(void (*)(), std::chrono::milliseconds interval, bool once,
const bool& user_exit);
#endif

void mock_stop_all();
Expand Down

0 comments on commit 36386f8

Please sign in to comment.