Commit 0e6088ec authored by Kirill Smelkov's avatar Kirill Smelkov

time: Offload users from thinking about refptr

Rearrange time C++ API so that e.g. time.Ticker is already
refptr<time._Ticker>. This way time users don't need to write refptr
all the time.
parent 5f76f363
...@@ -61,13 +61,11 @@ cdef extern from "golang/time.h" namespace "golang::time" nogil: ...@@ -61,13 +61,11 @@ cdef extern from "golang/time.h" namespace "golang::time" nogil:
chan[double] after(double dt) chan[double] after(double dt)
Timer after_func(double dt, ...) # ... = std::function<void()> Timer after_func(double dt, ...) # ... = std::function<void()>
# pyx _Ticker = raw C++ Ticker cppclass _Ticker:
cppclass _Ticker "Ticker":
chan[double] c chan[double] c
void stop() void stop()
# pyx Ticker = C++ refptr<Ticker> cppclass Ticker (refptr[_Ticker]):
cppclass Ticker "golang::refptr<golang::time::Ticker>" (refptr[_Ticker]):
# Ticker.X = Ticker->X in C++. # Ticker.X = Ticker->X in C++.
chan[double] c "_ptr()->c" chan[double] c "_ptr()->c"
void stop "_ptr()->stop" () void stop "_ptr()->stop" ()
...@@ -75,14 +73,12 @@ cdef extern from "golang/time.h" namespace "golang::time" nogil: ...@@ -75,14 +73,12 @@ cdef extern from "golang/time.h" namespace "golang::time" nogil:
Ticker new_ticker(double dt) Ticker new_ticker(double dt)
# pyx _Timer = raw C++ Timer cppclass _Timer:
cppclass _Timer "Timer":
chan[double] c chan[double] c
cbool stop() cbool stop()
void reset(double dt) void reset(double dt)
# pyx Timer = C++ refptr<Timer> cppclass Timer (refptr[_Timer]):
cppclass Timer "golang::refptr<golang::time::Timer>" (refptr[_Timer]):
# Timer.X = Timer->X in C++. # Timer.X = Timer->X in C++.
chan[double] c "_ptr()->c" chan[double] c "_ptr()->c"
cbool stop "_ptr()->stop" () cbool stop "_ptr()->stop" ()
......
...@@ -34,9 +34,9 @@ namespace time { ...@@ -34,9 +34,9 @@ namespace time {
// ---- timers ---- // ---- timers ----
// FIXME timers are implemented very inefficiently - each timer currently consumes a goroutine. // FIXME timers are implemented very inefficiently - each timer currently consumes a goroutine.
refptr<Ticker> new_ticker(double dt); Ticker new_ticker(double dt);
refptr<Timer> new_timer (double dt); Timer new_timer (double dt);
refptr<Timer> _new_timer(double dt, function<void()>); Timer _new_timer(double dt, function<void()>);
chan<double> tick(double dt) { chan<double> tick(double dt) {
...@@ -49,23 +49,23 @@ chan<double> after(double dt) { ...@@ -49,23 +49,23 @@ chan<double> after(double dt) {
return new_timer(dt)->c; return new_timer(dt)->c;
} }
refptr<Timer> after_func(double dt, function<void()> f) { Timer after_func(double dt, function<void()> f) {
return _new_timer(dt, f); return _new_timer(dt, f);
} }
// Ticker // Ticker
Ticker::Ticker() {} _Ticker::_Ticker() {}
Ticker::~Ticker() {} _Ticker::~_Ticker() {}
void Ticker::decref() { void _Ticker::decref() {
if (__decref()) if (__decref())
delete this; delete this;
} }
refptr<Ticker> new_ticker(double dt) { Ticker new_ticker(double dt) {
if (dt <= 0) if (dt <= 0)
panic("ticker: dt <= 0"); panic("ticker: dt <= 0");
refptr<Ticker> tx = adoptref(new Ticker()); Ticker tx = adoptref(new _Ticker());
tx->c = makechan<double>(1); // 1-buffer -- same as in Go tx->c = makechan<double>(1); // 1-buffer -- same as in Go
tx->_dt = dt; tx->_dt = dt;
tx->_stop = false; tx->_stop = false;
...@@ -75,8 +75,8 @@ refptr<Ticker> new_ticker(double dt) { ...@@ -75,8 +75,8 @@ refptr<Ticker> new_ticker(double dt) {
return tx; return tx;
} }
void Ticker::stop() { void _Ticker::stop() {
Ticker &tx = *this; _Ticker &tx = *this;
tx._mu.lock(); tx._mu.lock();
tx._stop = true; tx._stop = true;
...@@ -87,8 +87,8 @@ void Ticker::stop() { ...@@ -87,8 +87,8 @@ void Ticker::stop() {
tx._mu.unlock(); tx._mu.unlock();
} }
void Ticker::_tick() { void _Ticker::_tick() {
Ticker &tx = *this; _Ticker &tx = *this;
while (1) { while (1) {
// XXX adjust for accumulated error δ? // XXX adjust for accumulated error δ?
...@@ -113,15 +113,15 @@ void Ticker::_tick() { ...@@ -113,15 +113,15 @@ void Ticker::_tick() {
// Timer // Timer
Timer::Timer() {} _Timer::_Timer() {}
Timer::~Timer() {} _Timer::~_Timer() {}
void Timer::decref() { void _Timer::decref() {
if (__decref()) if (__decref())
delete this; delete this;
} }
refptr<Timer> _new_timer(double dt, function<void()> f) { Timer _new_timer(double dt, function<void()> f) {
refptr<Timer> t = adoptref(new Timer()); Timer t = adoptref(new _Timer());
t->c = (f == NULL ? makechan<double>(1) : NULL); t->c = (f == NULL ? makechan<double>(1) : NULL);
t->_f = f; t->_f = f;
t->_dt = INFINITY; t->_dt = INFINITY;
...@@ -130,12 +130,12 @@ refptr<Timer> _new_timer(double dt, function<void()> f) { ...@@ -130,12 +130,12 @@ refptr<Timer> _new_timer(double dt, function<void()> f) {
return t; return t;
} }
refptr<Timer> new_timer(double dt) { Timer new_timer(double dt) {
return _new_timer(dt, NULL); return _new_timer(dt, NULL);
} }
bool Timer::stop() { bool _Timer::stop() {
Timer &t = *this; _Timer &t = *this;
bool canceled; bool canceled;
t._mu.lock(); t._mu.lock();
...@@ -157,8 +157,8 @@ bool Timer::stop() { ...@@ -157,8 +157,8 @@ bool Timer::stop() {
return canceled; return canceled;
} }
void Timer::reset(double dt) { void _Timer::reset(double dt) {
Timer &t = *this; _Timer &t = *this;
t._mu.lock(); t._mu.lock();
if (t._dt != INFINITY) { if (t._dt != INFINITY) {
...@@ -168,15 +168,15 @@ void Timer::reset(double dt) { ...@@ -168,15 +168,15 @@ void Timer::reset(double dt) {
t._dt = dt; t._dt = dt;
t._ver += 1; t._ver += 1;
// TODO rework timers so that new timer does not spawn new goroutine. // TODO rework timers so that new timer does not spawn new goroutine.
refptr<Timer> tref = newref(&t); // pass t reference to spawned goroutine Timer tref = newref(&t); // pass t reference to spawned goroutine
go([tref, dt](int ver) { go([tref, dt](int ver) {
tref->_fire(dt, ver); tref->_fire(dt, ver);
}, t._ver); }, t._ver);
t._mu.unlock(); t._mu.unlock();
} }
void Timer::_fire(double dt, int ver) { void _Timer::_fire(double dt, int ver) {
Timer &t = *this; _Timer &t = *this;
sleep(dt); sleep(dt);
t._mu.lock(); t._mu.lock();
......
...@@ -74,8 +74,10 @@ LIBGOLANG_API void sleep(double dt); ...@@ -74,8 +74,10 @@ LIBGOLANG_API void sleep(double dt);
LIBGOLANG_API double now(); LIBGOLANG_API double now();
class Ticker; class _Ticker;
class Timer; class _Timer;
typedef refptr<_Ticker> Ticker;
typedef refptr<_Timer> Timer;
// tick returns channel connected to dt ticker. // tick returns channel connected to dt ticker.
// //
...@@ -92,17 +94,17 @@ LIBGOLANG_API chan<double> after(double dt); ...@@ -92,17 +94,17 @@ LIBGOLANG_API chan<double> after(double dt);
// //
// The function will be called in its own goroutine. // The function will be called in its own goroutine.
// Returned timer can be used to cancel the call. // Returned timer can be used to cancel the call.
LIBGOLANG_API refptr<Timer> after_func(double dt, std::function<void()> f); LIBGOLANG_API Timer after_func(double dt, std::function<void()> f);
// new_ticker creates new Ticker that will be firing at dt intervals. // new_ticker creates new Ticker that will be firing at dt intervals.
LIBGOLANG_API refptr<Ticker> new_ticker(double dt); LIBGOLANG_API Ticker new_ticker(double dt);
// Ticker arranges for time events to be sent to .c channel on dt-interval basis. // Ticker arranges for time events to be sent to .c channel on dt-interval basis.
// //
// If the receiver is slow, Ticker does not queue events and skips them. // If the receiver is slow, Ticker does not queue events and skips them.
// Ticking can be canceled via .stop() . // Ticking can be canceled via .stop() .
struct Ticker : refobj { struct _Ticker : refobj {
chan<double> c; chan<double> c;
private: private:
...@@ -112,9 +114,9 @@ private: ...@@ -112,9 +114,9 @@ private:
// don't new - create only via new_ticker() // don't new - create only via new_ticker()
private: private:
Ticker(); _Ticker();
~Ticker(); ~_Ticker();
friend refptr<Ticker> new_ticker(double dt); friend Ticker new_ticker(double dt);
public: public:
LIBGOLANG_API void decref(); LIBGOLANG_API void decref();
...@@ -130,12 +132,12 @@ private: ...@@ -130,12 +132,12 @@ private:
// new_timer creates new Timer that will fire after dt. // new_timer creates new Timer that will fire after dt.
LIBGOLANG_API refptr<Timer> new_timer(double dt); LIBGOLANG_API Timer new_timer(double dt);
// Timer arranges for time event to be sent to .c channel after dt time. // Timer arranges for time event to be sent to .c channel after dt time.
// //
// The timer can be stopped (.stop), or reinitialized to another time (.reset). // The timer can be stopped (.stop), or reinitialized to another time (.reset).
struct Timer : refobj { struct _Timer : refobj {
chan<double> c; chan<double> c;
private: private:
...@@ -147,9 +149,9 @@ private: ...@@ -147,9 +149,9 @@ private:
// don't new - create only via new_timer() & co // don't new - create only via new_timer() & co
private: private:
Timer(); _Timer();
~Timer(); ~_Timer();
friend refptr<Timer> _new_timer(double dt, std::function<void()> f); friend Timer _new_timer(double dt, std::function<void()> f);
public: public:
LIBGOLANG_API void decref(); LIBGOLANG_API void decref();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment