Last active
November 24, 2016 09:47
-
-
Save kaoskorobase/4d0468e2308d7dd92b19d9b8e0df5c44 to your computer and use it in GitHub Desktop.
sodium-cxx event at time 0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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