Skip to content

Instantly share code, notes, and snippets.

@kaoskorobase
Last active November 24, 2016 09:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaoskorobase/4d0468e2308d7dd92b19d9b8e0df5c44 to your computer and use it in GitHub Desktop.
Save kaoskorobase/4d0468e2308d7dd92b19d9b8e0df5c44 to your computer and use it in GitHub Desktop.
sodium-cxx event at time 0
#include "gtest/gtest.h"
#include <sodium/sodium.h>
#include <sodium/time.h>
using namespace sodium;
using namespace std;
using boost::optional;
using boost::make_optional;
namespace
{
int next_seq = 0;
struct test_impl : sodium::timer_system_impl<double>
{
test_impl() : now_(0) {}
struct entry {
entry(double t_, std::function<void()> callback_)
: t(t_), callback(callback_), seq(++next_seq) {}
double t;
std::function<void()> callback;
int seq;
bool operator < (const entry& other) const {
if (t > other.t) return true;
if (t < other.t) return false;
return seq > other.seq;
}
bool operator == (const entry& other) const {
return seq == other.seq;
}
};
sodium::impl::thread_safe_priority_queue<entry> entries;
double now_;
/*!
* Set a timer that will execute the specified callback at the specified time.
* @return A function that can be used to cancel the timer.
*/
virtual std::function<void()> set_timer(double t, std::function<void()> callback)
{
entry e(t, callback);
entries.push(entry(t, callback));
return [this, e] () {
entries.remove(e);
};
}
/**
* Return the current clock time.
*/
virtual double now() {
return now_;
}
void set_time(double t) {
while (true) {
boost::optional<entry> oe = entries.pop_if([t] (const entry& e) {
return e.t <= t;
});
if (oe)
oe.get().callback();
else
break;
}
now_ = t;
}
};
stream<double> onsetEvent(const sodium::timer_system<double>& timeSys, double dt) {
transaction t;
cell_loop<optional<double>> oOnsetAlarm;
stream<double> sOnset = timeSys.at(oOnsetAlarm);
oOnsetAlarm.loop(
sOnset.map([](double) { return optional<double>(); })
.hold(make_optional(timeSys.time.sample() + dt))
);
return sOnset;
}
} // namespace
TEST(OnsetEvent_Test, should_fire_at_time_0)
{
std::shared_ptr<test_impl> impl(new test_impl);
sodium::timer_system<double> ts(impl);
stream<double> onset0 = onsetEvent(ts, 0);
stream<double> onset1 = onsetEvent(ts, 0.5);
auto kill0 = onset0.listen([](double t) {
std::cout << "onset0 " << t << std::endl;
});
auto kill1 = onset1.listen([](double t) {
std::cout << "onset1 " << t << std::endl;
});
for (double t = 0; t <= 10; t += 0.1) {
std::cout << "t " << t << std::endl;
impl->set_time(t);
}
// If these are omitted, nothing is printed.
kill0();
kill1();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment