Commit fc1c3e24 authored by Kirill Smelkov's avatar Kirill Smelkov

*: NULL/nullptr -> nil (C++ only)

Convert C++ part of the project to use nil instead of NULL/nullptr.

We do not convert pyx part yet, because Cython currently does not
understand that nullptr_t has properties of NULL and with e.g. the
following change

    --- a/golang/_context.pyx
    +++ b/golang/_context.pyx
    @@ -116,7 +116,7 @@ cdef cppclass _PyValue (_interface, gobject) nogil:
         __dealloc__():
             with gil:
                 obj = <object>this.pyobj
    -            this.pyobj = NULL
    +            this.pyobj = nil
                 Py_DECREF(obj)

errors as

    Error compiling Cython file:
    ------------------------------------------------------------
    ...
            if __decref():
                del self
        __dealloc__():
            with gil:
                obj = <object>this.pyobj
                this.pyobj = nil
                            ^
    ------------------------------------------------------------

    golang/_context.pyx:119:25: Cannot assign type 'nullptr_t' to 'PyObject *'

https://github.com/cython/cython/issues/3314
parent 60f6db6f
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -53,9 +53,9 @@ struct _Background final : _Context, object { ...@@ -53,9 +53,9 @@ struct _Background final : _Context, object {
} }
double deadline() { return INFINITY; } double deadline() { return INFINITY; }
chan<structZ> done() { return NULL; } chan<structZ> done() { return nil; }
error err() { return NULL; } error err() { return nil; }
interface value(const void *key) { return NULL; } interface value(const void *key) { return nil; }
}; };
static Context _background = adoptref(static_cast<_Context *>(new _Background())); static Context _background = adoptref(static_cast<_Context *>(new _Background()));
...@@ -98,7 +98,7 @@ struct _BaseCtx : _Context, object { ...@@ -98,7 +98,7 @@ struct _BaseCtx : _Context, object {
// chan: if context can be canceled on its own // chan: if context can be canceled on its own
// nil: if context can not be canceled on its own // nil: if context can not be canceled on its own
ctx._done = done; ctx._done = done;
if (done == NULL) { if (done == nil) {
if (parentv.size() != 1) if (parentv.size() != 1)
panic("BUG: _BaseCtx: done==nil, but len(parentv) != 1"); panic("BUG: _BaseCtx: done==nil, but len(parentv) != 1");
} }
...@@ -109,7 +109,7 @@ struct _BaseCtx : _Context, object { ...@@ -109,7 +109,7 @@ struct _BaseCtx : _Context, object {
chan<structZ> done() { chan<structZ> done() {
_BaseCtx& ctx = *this; _BaseCtx& ctx = *this;
if (ctx._done != NULL) if (ctx._done != nil)
return ctx._done; return ctx._done;
return ctx._parentv[0]->done(); return ctx._parentv[0]->done();
} }
...@@ -130,10 +130,10 @@ struct _BaseCtx : _Context, object { ...@@ -130,10 +130,10 @@ struct _BaseCtx : _Context, object {
for (auto parent : ctx._parentv) { for (auto parent : ctx._parentv) {
interface v = parent->value(key); interface v = parent->value(key);
if (v != NULL) if (v != nil)
return v; return v;
} }
return NULL; return nil;
} }
double deadline() { double deadline() {
...@@ -152,7 +152,7 @@ struct _BaseCtx : _Context, object { ...@@ -152,7 +152,7 @@ struct _BaseCtx : _Context, object {
// _cancel cancels ctx and its children. // _cancel cancels ctx and its children.
void _cancel(error err) { void _cancel(error err) {
_BaseCtx& ctx = *this; _BaseCtx& ctx = *this;
return ctx._cancelFrom(NULL, err); return ctx._cancelFrom(nil, err);
} }
// _cancelFrom cancels ctx and its children. // _cancelFrom cancels ctx and its children.
...@@ -162,7 +162,7 @@ struct _BaseCtx : _Context, object { ...@@ -162,7 +162,7 @@ struct _BaseCtx : _Context, object {
set<refptr<_BaseCtx>> children; set<refptr<_BaseCtx>> children;
ctx._mu.lock(); ctx._mu.lock();
if (ctx._err != NULL) { if (ctx._err != nil) {
ctx._mu.unlock(); ctx._mu.unlock();
return; // already canceled return; // already canceled
} }
...@@ -171,7 +171,7 @@ struct _BaseCtx : _Context, object { ...@@ -171,7 +171,7 @@ struct _BaseCtx : _Context, object {
ctx._children.swap(children); ctx._children.swap(children);
ctx._mu.unlock(); ctx._mu.unlock();
if (ctx._done != NULL) if (ctx._done != nil)
ctx._done.close(); ctx._done.close();
// no longer need to propagate cancel from parent after we are canceled // no longer need to propagate cancel from parent after we are canceled
...@@ -180,7 +180,7 @@ struct _BaseCtx : _Context, object { ...@@ -180,7 +180,7 @@ struct _BaseCtx : _Context, object {
if (parent == cancelFrom) if (parent == cancelFrom)
continue; continue;
_BaseCtx *_parent = dynamic_cast<_BaseCtx *>(parent._ptr()); _BaseCtx *_parent = dynamic_cast<_BaseCtx *>(parent._ptr());
if (_parent != NULL) { if (_parent != nil) {
_parent->_mu.lock(); _parent->_mu.lock();
_parent->_children.erase(bctx); _parent->_children.erase(bctx);
_parent->_mu.unlock(); _parent->_mu.unlock();
...@@ -204,14 +204,14 @@ struct _BaseCtx : _Context, object { ...@@ -204,14 +204,14 @@ struct _BaseCtx : _Context, object {
// if parent can never be canceled (e.g. it is background) - we // if parent can never be canceled (e.g. it is background) - we
// don't need to propagate cancel from it. // don't need to propagate cancel from it.
chan<structZ> pdone = parent->done(); chan<structZ> pdone = parent->done();
if (pdone == NULL) if (pdone == nil)
continue; continue;
// parent is cancellable - glue to propagate cancel from it to us // parent is cancellable - glue to propagate cancel from it to us
_BaseCtx *_parent = dynamic_cast<_BaseCtx *>(parent._ptr()); _BaseCtx *_parent = dynamic_cast<_BaseCtx *>(parent._ptr());
if (_parent != NULL) { if (_parent != nil) {
_parent->_mu.lock(); _parent->_mu.lock();
if (_parent->_err != NULL) if (_parent->_err != nil)
ctx._cancel(_parent->_err); ctx._cancel(_parent->_err);
else else
_parent->_children.insert(bctx); _parent->_children.insert(bctx);
...@@ -259,7 +259,7 @@ struct _ValueCtx : _BaseCtx { ...@@ -259,7 +259,7 @@ struct _ValueCtx : _BaseCtx {
interface _value; interface _value;
_ValueCtx(const void *key, interface value, Context parent) _ValueCtx(const void *key, interface value, Context parent)
: _BaseCtx(NULL, {parent}) { : _BaseCtx(nil, {parent}) {
_ValueCtx& ctx = *this; _ValueCtx& ctx = *this;
ctx._key = key; ctx._key = key;
...@@ -363,7 +363,7 @@ static bool _ready(chan<structZ> ch) { ...@@ -363,7 +363,7 @@ static bool _ready(chan<structZ> ch) {
// _tctxchildren returns context's children, assuming context is instance of _BaseCtx. // _tctxchildren returns context's children, assuming context is instance of _BaseCtx.
set<Context> _tctxchildren(Context ctx) { set<Context> _tctxchildren(Context ctx) {
_BaseCtx *_bctx = dynamic_cast<_BaseCtx*>(ctx._ptr()); _BaseCtx *_bctx = dynamic_cast<_BaseCtx*>(ctx._ptr());
if (_bctx == NULL) if (_bctx == nil)
panic("context is not instance of golang.context._BaseCtx"); panic("context is not instance of golang.context._BaseCtx");
set<Context> children; set<Context> children;
......
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -38,7 +38,7 @@ string _vsprintf(const char *format, va_list argp) { ...@@ -38,7 +38,7 @@ string _vsprintf(const char *format, va_list argp) {
// based on https://stackoverflow.com/a/26221725/9456786 // based on https://stackoverflow.com/a/26221725/9456786
va_list argp2; va_list argp2;
va_copy(argp2, argp); va_copy(argp2, argp);
size_t nchar = ::vsnprintf(NULL, 0, format, argp2); size_t nchar = ::vsnprintf(nil, 0, format, argp2);
va_end(argp2); va_end(argp2);
std::unique_ptr<char[]> buf( new char[nchar /*for \0*/+1] ); std::unique_ptr<char[]> buf( new char[nchar /*for \0*/+1] );
......
...@@ -412,14 +412,14 @@ class chan { ...@@ -412,14 +412,14 @@ class chan {
_chan *_ch; _chan *_ch;
public: public:
inline chan() { _ch = NULL; } // nil channel if not explicitly initialized inline chan() { _ch = nil; } // nil channel if not explicitly initialized
friend chan<T> makechan<T>(unsigned size); friend chan<T> makechan<T>(unsigned size);
friend chan<T> _wrapchan<T>(_chan *_ch); friend chan<T> _wrapchan<T>(_chan *_ch);
inline ~chan() { _chanxdecref(_ch); _ch = NULL; } inline ~chan() { _chanxdecref(_ch); _ch = nil; }
// = nil // = nil
inline chan(nullptr_t) { _ch = NULL; } inline chan(nullptr_t) { _ch = nil; }
inline chan& operator=(nullptr_t) { _chanxdecref(_ch); _ch = NULL; return *this; } inline chan& operator=(nullptr_t) { _chanxdecref(_ch); _ch = nil; return *this; }
// copy // copy
inline chan(const chan& from) { _ch = from._ch; _chanxincref(_ch); } inline chan(const chan& from) { _ch = from._ch; _chanxincref(_ch); }
inline chan& operator=(const chan& from) { inline chan& operator=(const chan& from) {
...@@ -429,10 +429,10 @@ public: ...@@ -429,10 +429,10 @@ public:
return *this; return *this;
} }
// move // move
inline chan(chan&& from) { _ch = from._ch; from._ch = NULL; } inline chan(chan&& from) { _ch = from._ch; from._ch = nil; }
inline chan& operator=(chan&& from) { inline chan& operator=(chan&& from) {
if (this != &from) { if (this != &from) {
_chanxdecref(_ch); _ch = from._ch; from._ch = NULL; _chanxdecref(_ch); _ch = from._ch; from._ch = nil;
} }
return *this; return *this;
} }
...@@ -457,7 +457,7 @@ public: ...@@ -457,7 +457,7 @@ public:
// //
// if pok is provided the case is extended to `[*prx, *pok] = ch.recv_()` // if pok is provided the case is extended to `[*prx, *pok] = ch.recv_()`
// if both prx and pok are omitted the case is reduced to `ch.recv()`. // if both prx and pok are omitted the case is reduced to `ch.recv()`.
[[nodiscard]] inline _selcase recvs(T *prx=NULL, bool *pok=NULL) const { [[nodiscard]] inline _selcase recvs(T *prx=nil, bool *pok=nil) const {
return _selrecv_(_ch, prx, pok); return _selrecv_(_ch, prx, pok);
} }
...@@ -466,8 +466,8 @@ public: ...@@ -466,8 +466,8 @@ public:
inline unsigned cap() const { return _chancap(_ch); } inline unsigned cap() const { return _chancap(_ch); }
// compare wrt nil // compare wrt nil
inline bool operator==(nullptr_t) const { return (_ch == NULL); } inline bool operator==(nullptr_t) const { return (_ch == nil); }
inline bool operator!=(nullptr_t) const { return (_ch != NULL); } inline bool operator!=(nullptr_t) const { return (_ch != nil); }
// compare wrt chan // compare wrt chan
inline bool operator==(const chan<T>& ch2) const { return (_ch == ch2._ch); } inline bool operator==(const chan<T>& ch2) const { return (_ch == ch2._ch); }
...@@ -494,7 +494,7 @@ chan<T> makechan(unsigned size) { ...@@ -494,7 +494,7 @@ chan<T> makechan(unsigned size) {
} }
// _wrapchan<T> wraps raw channel with chan<T>. // _wrapchan<T> wraps raw channel with chan<T>.
// raw channel must be either NULL or its element size must correspond to T. // raw channel must be either nil or its element size must correspond to T.
LIBGOLANG_API void __wrapchan(_chan *_ch, unsigned elemsize); LIBGOLANG_API void __wrapchan(_chan *_ch, unsigned elemsize);
template<typename T> static inline template<typename T> static inline
chan<T> _wrapchan(_chan *_ch) { chan<T> _wrapchan(_chan *_ch) {
...@@ -577,36 +577,36 @@ class refptr { ...@@ -577,36 +577,36 @@ class refptr {
public: public:
// nil if not explicitly initialized // nil if not explicitly initialized
inline refptr() { _obj = NULL; } inline refptr() { _obj = nil; }
inline ~refptr() { inline ~refptr() {
if (_obj != NULL) { if (_obj != nil) {
_obj->decref(); _obj->decref();
_obj = NULL; _obj = nil;
} }
} }
// = nil // = nil
inline refptr(nullptr_t) { _obj = NULL; } inline refptr(nullptr_t) { _obj = nil; }
inline refptr& operator=(nullptr_t) { inline refptr& operator=(nullptr_t) {
if (_obj != NULL) if (_obj != nil)
_obj->decref(); _obj->decref();
_obj = NULL; _obj = nil;
return *this; return *this;
} }
// copy // copy
inline refptr(const refptr& from) { inline refptr(const refptr& from) {
_obj = from._obj; _obj = from._obj;
if(_obj != NULL) if (_obj != nil)
_obj->incref(); _obj->incref();
} }
inline refptr& operator=(const refptr& from) { inline refptr& operator=(const refptr& from) {
if (this != &from) { if (this != &from) {
if (_obj != NULL) if (_obj != nil)
_obj->decref(); _obj->decref();
_obj = from._obj; _obj = from._obj;
if (_obj != NULL) if (_obj != nil)
_obj->incref(); _obj->incref();
} }
return *this; return *this;
...@@ -615,14 +615,14 @@ public: ...@@ -615,14 +615,14 @@ public:
// move // move
inline refptr(refptr&& from) { inline refptr(refptr&& from) {
_obj = from._obj; _obj = from._obj;
from._obj = NULL; from._obj = nil;
} }
inline refptr& operator=(refptr&& from) { inline refptr& operator=(refptr&& from) {
if (this != &from) { if (this != &from) {
if (_obj != NULL) if (_obj != nil)
_obj->decref(); _obj->decref();
_obj = from._obj; _obj = from._obj;
from._obj = NULL; from._obj = nil;
} }
return *this; return *this;
} }
...@@ -632,8 +632,8 @@ public: ...@@ -632,8 +632,8 @@ public:
friend refptr<T> newref<T> (T *_obj); friend refptr<T> newref<T> (T *_obj);
// compare wrt nil // compare wrt nil
inline bool operator==(nullptr_t) const { return (_obj == NULL); } inline bool operator==(nullptr_t) const { return (_obj == nil); }
inline bool operator!=(nullptr_t) const { return (_obj != NULL); } inline bool operator!=(nullptr_t) const { return (_obj != nil); }
// compare wrt refptr // compare wrt refptr
inline bool operator==(const refptr& p2) const { return (_obj == p2._obj); } inline bool operator==(const refptr& p2) const { return (_obj == p2._obj); }
...@@ -681,21 +681,21 @@ public: ...@@ -681,21 +681,21 @@ public:
} }
// nil if not explicitly initialized // nil if not explicitly initialized
inline global() { _obj = NULL; } inline global() { _obj = nil; }
// init from refptr<T> // init from refptr<T>
inline global(const refptr<T>& from) { inline global(const refptr<T>& from) {
_obj = from._obj; _obj = from._obj;
if (_obj != NULL) if (_obj != nil)
_obj->incref(); _obj->incref();
} }
// = nil // = nil
inline global(nullptr_t) { _obj = NULL; } inline global(nullptr_t) { _obj = nil; }
inline global& operator=(nullptr_t) { inline global& operator=(nullptr_t) {
if (_obj != NULL) if (_obj != nil)
_obj->decref(); _obj->decref();
_obj = NULL; _obj = nil;
return *this; return *this;
} }
...@@ -703,8 +703,8 @@ public: ...@@ -703,8 +703,8 @@ public:
// move - no need due to refptr<T> cast // move - no need due to refptr<T> cast
// compare wrt nil // compare wrt nil
inline bool operator==(nullptr_t) const { return (_obj == NULL); } inline bool operator==(nullptr_t) const { return (_obj == nil); }
inline bool operator!=(nullptr_t) const { return (_obj != NULL); } inline bool operator!=(nullptr_t) const { return (_obj != nil); }
// compare wrt refptr // compare wrt refptr
inline bool operator==(const refptr<T>& p2) const { return (_obj == p2._obj); } inline bool operator==(const refptr<T>& p2) const { return (_obj == p2._obj); }
...@@ -747,7 +747,7 @@ template<typename T> ...@@ -747,7 +747,7 @@ template<typename T>
inline refptr<T> newref(T *_obj) { inline refptr<T> newref(T *_obj) {
refptr<T> p; refptr<T> p;
p._obj = _obj; p._obj = _obj;
if (_obj != NULL) if (_obj != nil)
_obj->incref(); _obj->incref();
return p; return p;
} }
......
// Copyright (C) 2018-2019 Nexedi SA and Contributors. // Copyright (C) 2018-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -57,10 +57,11 @@ using std::numeric_limits; ...@@ -57,10 +57,11 @@ using std::numeric_limits;
using std::unique_ptr; using std::unique_ptr;
using std::vector; using std::vector;
static void *zalloc(size_t size); // golang::
namespace golang { namespace golang {
static void *zalloc(size_t size);
// ---- panic ---- // ---- panic ----
struct PanicError : exception { struct PanicError : exception {
...@@ -79,7 +80,7 @@ struct PanicError : exception { ...@@ -79,7 +80,7 @@ struct PanicError : exception {
} }
// recover recovers from exception thrown by panic. // recover recovers from exception thrown by panic.
// it returns: !NULL - there was panic with that argument. NULL - there was no panic. // it returns: !nil - there was panic with that argument. nil - there was no panic.
// if another exception was thrown - recover rethrows it. // if another exception was thrown - recover rethrows it.
const char *recover() { const char *recover() {
// if PanicError was thrown - recover from it // if PanicError was thrown - recover from it
...@@ -89,7 +90,7 @@ const char *recover() { ...@@ -89,7 +90,7 @@ const char *recover() {
return exc.arg; return exc.arg;
} }
return NULL; return nil;
} }
...@@ -110,11 +111,11 @@ struct Bug : exception { ...@@ -110,11 +111,11 @@ struct Bug : exception {
// ---- runtime ---- // ---- runtime ----
// initially NULL to crash if runtime was not initialized // initially nil to crash if runtime was not initialized
static const _libgolang_runtime_ops *_runtime = NULL; static const _libgolang_runtime_ops *_runtime = nil;
void _libgolang_init(const _libgolang_runtime_ops *runtime_ops) { void _libgolang_init(const _libgolang_runtime_ops *runtime_ops) {
if (_runtime != NULL) // XXX better check atomically if (_runtime != nil) // XXX better check atomically
panic("libgolang: double init"); panic("libgolang: double init");
_runtime = runtime_ops; _runtime = runtime_ops;
} }
...@@ -132,7 +133,7 @@ namespace sync { ...@@ -132,7 +133,7 @@ namespace sync {
// _makesema creates new semaphore. // _makesema creates new semaphore.
// //
// it always returns !NULL and panics on memory allocation failue. // it always returns !nil and panics on memory allocation failue.
_sema *_makesema() { _sema *_makesema() {
_sema *sema = (_sema *)_runtime->sema_alloc(); _sema *sema = (_sema *)_runtime->sema_alloc();
if (!sema) if (!sema)
...@@ -161,7 +162,7 @@ Sema::Sema() { ...@@ -161,7 +162,7 @@ Sema::Sema() {
Sema::~Sema() { Sema::~Sema() {
Sema *sema = this; Sema *sema = this;
_semafree(sema->_gsema); _semafree(sema->_gsema);
sema->_gsema = NULL; sema->_gsema = nil;
} }
void Sema::acquire() { void Sema::acquire() {
...@@ -297,7 +298,7 @@ struct _RecvSendWaiting { ...@@ -297,7 +298,7 @@ struct _RecvSendWaiting {
list_head in_rxtxq; // in recv or send queue of the channel (_chan._recvq|_sendq -> _) list_head in_rxtxq; // in recv or send queue of the channel (_chan._recvq|_sendq -> _)
// recv: on wakeup: sender|closer -> receiver; NULL means "don't copy received value" // recv: on wakeup: sender|closer -> receiver; nil means "don't copy received value"
// send: ptr-to data to send // send: ptr-to data to send
void *pdata; void *pdata;
// on wakeup: whether recv/send succeeded (send fails on close) // on wakeup: whether recv/send succeeded (send fails on close)
...@@ -345,12 +346,12 @@ _RecvSendWaiting::_RecvSendWaiting() { ...@@ -345,12 +346,12 @@ _RecvSendWaiting::_RecvSendWaiting() {
// init initializes waiter to be part of group waiting on ch. // init initializes waiter to be part of group waiting on ch.
void _RecvSendWaiting::init(_WaitGroup *group, _chan *ch) { void _RecvSendWaiting::init(_WaitGroup *group, _chan *ch) {
_RecvSendWaiting *w = this; _RecvSendWaiting *w = this;
if (w->group != NULL) if (w->group != nil)
bug("_RecvSendWaiting: double init"); bug("_RecvSendWaiting: double init");
w->group = group; w->group = group;
w->chan = ch; w->chan = ch;
INIT_LIST_HEAD(&w->in_rxtxq); INIT_LIST_HEAD(&w->in_rxtxq);
w->pdata = NULL; w->pdata = nil;
w->ok = false; w->ok = false;
w->sel_n = -1; w->sel_n = -1;
} }
...@@ -365,7 +366,7 @@ void _RecvSendWaiting::wakeup(bool ok) { ...@@ -365,7 +366,7 @@ void _RecvSendWaiting::wakeup(bool ok) {
_WaitGroup::_WaitGroup() { _WaitGroup::_WaitGroup() {
_WaitGroup *group = this; _WaitGroup *group = this;
group->_sema.acquire(); group->_sema.acquire();
group->which = NULL; group->which = nil;
} }
// try_to_win tries to win waiter after it was dequeued from a channel's {_send|_recv}q. // try_to_win tries to win waiter after it was dequeued from a channel's {_send|_recv}q.
...@@ -376,7 +377,7 @@ bool _WaitGroup::try_to_win(_RecvSendWaiting *waiter) { // -> won ...@@ -376,7 +377,7 @@ bool _WaitGroup::try_to_win(_RecvSendWaiting *waiter) { // -> won
bool won; bool won;
group->_mu.lock(); group->_mu.lock();
if (group->which != NULL) { if (group->which != nil) {
won = false; won = false;
} }
else { else {
...@@ -403,7 +404,7 @@ void _WaitGroup::wait() { ...@@ -403,7 +404,7 @@ void _WaitGroup::wait() {
// notification. // notification.
void _WaitGroup::wakeup() { void _WaitGroup::wakeup() {
_WaitGroup *group = this; _WaitGroup *group = this;
if (group->which == NULL) if (group->which == nil)
bug("wakeup: group.which=nil"); bug("wakeup: group.which=nil");
group->_sema.release(); group->_sema.release();
} }
...@@ -426,17 +427,17 @@ _RecvSendWaiting *_dequeWaiter(list_head *queue) { ...@@ -426,17 +427,17 @@ _RecvSendWaiting *_dequeWaiter(list_head *queue) {
} }
} }
return NULL; return nil;
} }
// _makechan creates new _chan(elemsize, size). // _makechan creates new _chan(elemsize, size).
// //
// returned channel has refcnt=1. // returned channel has refcnt=1.
// _makechan always returns !NULL and panics on memory allocation failure. // _makechan always returns !nil and panics on memory allocation failure.
_chan *_makechan(unsigned elemsize, unsigned size) { _chan *_makechan(unsigned elemsize, unsigned size) {
_chan *ch; _chan *ch;
ch = (_chan *)zalloc(sizeof(_chan) + size*elemsize); ch = (_chan *)zalloc(sizeof(_chan) + size*elemsize);
if (ch == NULL) if (ch == nil)
panic("makechan: alloc failed"); panic("makechan: alloc failed");
new (ch) _chan(); // init .object, ._mu, ... new (ch) _chan(); // init .object, ._mu, ...
...@@ -452,7 +453,7 @@ _chan *_makechan(unsigned elemsize, unsigned size) { ...@@ -452,7 +453,7 @@ _chan *_makechan(unsigned elemsize, unsigned size) {
// __wrapchan serves _wrapchan<T>. // __wrapchan serves _wrapchan<T>.
void __wrapchan(_chan *ch, unsigned elemsize) { void __wrapchan(_chan *ch, unsigned elemsize) {
if (ch == NULL) if (ch == nil)
return; // nil, no elemsize checking return; // nil, no elemsize checking
if (ch->_elemsize != elemsize) if (ch->_elemsize != elemsize)
panic("wrapchan: elemsize mismatch"); panic("wrapchan: elemsize mismatch");
...@@ -463,7 +464,7 @@ void __wrapchan(_chan *ch, unsigned elemsize) { ...@@ -463,7 +464,7 @@ void __wrapchan(_chan *ch, unsigned elemsize) {
// //
// it is noop if ch=nil. // it is noop if ch=nil.
void _chanxincref(_chan *ch) { void _chanxincref(_chan *ch) {
if (ch == NULL) if (ch == nil)
return; return;
ch->incref(); ch->incref();
} }
...@@ -473,7 +474,7 @@ void _chanxincref(_chan *ch) { ...@@ -473,7 +474,7 @@ void _chanxincref(_chan *ch) {
// if refcnt goes to zero, the channel is deallocated. // if refcnt goes to zero, the channel is deallocated.
// it is noop if ch=nil. // it is noop if ch=nil.
void _chanxdecref(_chan *ch) { void _chanxdecref(_chan *ch) {
if (ch == NULL) if (ch == nil)
return; return;
ch->decref(); ch->decref();
} }
...@@ -509,8 +510,8 @@ void _blockforever(); ...@@ -509,8 +510,8 @@ void _blockforever();
// //
// sizeof(*ptx) must be ch._elemsize. // sizeof(*ptx) must be ch._elemsize.
void _chansend(_chan *ch, const void *ptx) { void _chansend(_chan *ch, const void *ptx) {
if (ch == NULL) // NOTE: cannot do this check in _chan::send if (ch == nil) // NOTE: cannot do this check in _chan::send
_blockforever(); // (C++ assumes `this` is never NULL and optimizes it out) _blockforever(); // (C++ assumes `this` is never nil and optimizes it out)
ch->send(ptx); ch->send(ptx);
} }
template<> void _chan::_send2</*onstack=*/true> (const void *ptx); template<> void _chan::_send2</*onstack=*/true> (const void *ptx);
...@@ -540,7 +541,7 @@ template<> void _chan::_send2</*onstack=*/false>(const void *ptx) { _chan *ch = ...@@ -540,7 +541,7 @@ template<> void _chan::_send2</*onstack=*/false>(const void *ptx) { _chan *ch =
// ptx stack -> heap (if ptx is on stack) TODO avoid copy if ptx is !onstack // ptx stack -> heap (if ptx is on stack) TODO avoid copy if ptx is !onstack
void *ptx_onheap = malloc(ch->_elemsize); void *ptx_onheap = malloc(ch->_elemsize);
if (ptx_onheap == NULL) { if (ptx_onheap == nil) {
ch->_mu.unlock(); ch->_mu.unlock();
throw bad_alloc(); throw bad_alloc();
} }
...@@ -572,9 +573,9 @@ void _chan::__send2(const void *ptx, _WaitGroup *g, _RecvSendWaiting *me) { _ch ...@@ -572,9 +573,9 @@ void _chan::__send2(const void *ptx, _WaitGroup *g, _RecvSendWaiting *me) { _ch
// ok is true - if receive was delivered by a successful send. // ok is true - if receive was delivered by a successful send.
// ok is false - if receive is due to channel being closed and empty. // ok is false - if receive is due to channel being closed and empty.
// //
// sizeof(*prx) must be ch._elemsize | prx=NULL. // sizeof(*prx) must be ch._elemsize | prx=nil.
bool _chanrecv_(_chan *ch, void *prx) { bool _chanrecv_(_chan *ch, void *prx) {
if (ch == NULL) if (ch == nil)
_blockforever(); _blockforever();
return ch->recv_(prx); return ch->recv_(prx);
} }
...@@ -603,13 +604,13 @@ template<> bool _chan::_recv2_</*onstack=*/false>(void *prx) { _chan *ch = this ...@@ -603,13 +604,13 @@ template<> bool _chan::_recv2_</*onstack=*/false>(void *prx) { _chan *ch = this
unique_ptr<_WaitGroup> g (new _WaitGroup); unique_ptr<_WaitGroup> g (new _WaitGroup);
unique_ptr<_RecvSendWaiting> me (new _RecvSendWaiting); unique_ptr<_RecvSendWaiting> me (new _RecvSendWaiting);
if (prx == NULL) if (prx == nil)
return __recv2_(prx, g.get(), me.get()); return __recv2_(prx, g.get(), me.get());
// prx stack -> onheap + copy back (if prx is on stack) TODO avoid copy if prx is !onstack // prx stack -> onheap + copy back (if prx is on stack) TODO avoid copy if prx is !onstack
unsigned ch_elemsize = ch->_elemsize; unsigned ch_elemsize = ch->_elemsize;
void *prx_onheap = malloc(ch_elemsize); void *prx_onheap = malloc(ch_elemsize);
if (prx_onheap == NULL) { if (prx_onheap == nil) {
ch->_mu.unlock(); ch->_mu.unlock();
throw bad_alloc(); throw bad_alloc();
} }
...@@ -638,9 +639,9 @@ bool _chan::__recv2_(void *prx, _WaitGroup *g, _RecvSendWaiting *me) { _chan *c ...@@ -638,9 +639,9 @@ bool _chan::__recv2_(void *prx, _WaitGroup *g, _RecvSendWaiting *me) { _chan *c
// recv receives from the channel. // recv receives from the channel.
// //
// if prx != NULL received value is put into *prx. // if prx != nil received value is put into *prx.
void _chanrecv(_chan *ch, void *prx) { void _chanrecv(_chan *ch, void *prx) {
if (ch == NULL) if (ch == nil)
_blockforever(); _blockforever();
ch->recv(prx); ch->recv(prx);
} }
...@@ -667,11 +668,11 @@ bool _chan::_trysend(const void *ptx) { // -> done ...@@ -667,11 +668,11 @@ bool _chan::_trysend(const void *ptx) { // -> done
// synchronous channel // synchronous channel
if (ch->_cap == 0) { if (ch->_cap == 0) {
_RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq); _RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq);
if (recv == NULL) if (recv == nil)
return false; return false;
ch->_mu.unlock(); ch->_mu.unlock();
if (recv->pdata != NULL) if (recv->pdata != nil)
memcpy(recv->pdata, ptx, ch->_elemsize); memcpy(recv->pdata, ptx, ch->_elemsize);
recv->wakeup(/*ok=*/true); recv->wakeup(/*ok=*/true);
return true; return true;
...@@ -683,7 +684,7 @@ bool _chan::_trysend(const void *ptx) { // -> done ...@@ -683,7 +684,7 @@ bool _chan::_trysend(const void *ptx) { // -> done
ch->_dataq_append(ptx); ch->_dataq_append(ptx);
_RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq); _RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq);
if (recv != NULL) { if (recv != nil) {
ch->_dataq_popleft(recv->pdata); ch->_dataq_popleft(recv->pdata);
ch->_mu.unlock(); ch->_mu.unlock();
recv->wakeup(/*ok=*/true); recv->wakeup(/*ok=*/true);
...@@ -702,7 +703,7 @@ bool _chan::_trysend(const void *ptx) { // -> done ...@@ -702,7 +703,7 @@ bool _chan::_trysend(const void *ptx) { // -> done
// if !done - returns with ._mu still being held. // if !done - returns with ._mu still being held.
// //
// if !done - (*prx, *pok) are left unmodified. // if !done - (*prx, *pok) are left unmodified.
// if prx=NULL received value is not copied into *prx. // if prx=nil received value is not copied into *prx.
bool _chan::_tryrecv(void *prx, bool *pok) { // -> done bool _chan::_tryrecv(void *prx, bool *pok) { // -> done
_chan *ch = this; _chan *ch = this;
...@@ -713,7 +714,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done ...@@ -713,7 +714,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done
// wakeup a blocked writer, if there is any // wakeup a blocked writer, if there is any
_RecvSendWaiting *send = _dequeWaiter(&ch->_sendq); _RecvSendWaiting *send = _dequeWaiter(&ch->_sendq);
if (send != NULL) { if (send != nil) {
ch->_dataq_append(send->pdata); ch->_dataq_append(send->pdata);
ch->_mu.unlock(); ch->_mu.unlock();
send->wakeup(/*ok=*/true); send->wakeup(/*ok=*/true);
...@@ -727,7 +728,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done ...@@ -727,7 +728,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done
// closed // closed
if (ch->_closed) { if (ch->_closed) {
ch->_mu.unlock(); ch->_mu.unlock();
if (prx != NULL) if (prx != nil)
memset(prx, 0, ch->_elemsize); memset(prx, 0, ch->_elemsize);
*pok = false; *pok = false;
return true; return true;
...@@ -735,11 +736,11 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done ...@@ -735,11 +736,11 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done
// sync | empty: there is waiting writer // sync | empty: there is waiting writer
_RecvSendWaiting *send = _dequeWaiter(&ch->_sendq); _RecvSendWaiting *send = _dequeWaiter(&ch->_sendq);
if (send == NULL) if (send == nil)
return false; return false;
ch->_mu.unlock(); ch->_mu.unlock();
if (prx != NULL) if (prx != nil)
memcpy(prx, send->pdata, ch->_elemsize); memcpy(prx, send->pdata, ch->_elemsize);
*pok = true; *pok = true;
send->wakeup(/*ok=*/true); send->wakeup(/*ok=*/true);
...@@ -748,7 +749,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done ...@@ -748,7 +749,7 @@ bool _chan::_tryrecv(void *prx, bool *pok) { // -> done
// close closes sending side of the channel. // close closes sending side of the channel.
void _chanclose(_chan *ch) { void _chanclose(_chan *ch) {
if (ch == NULL) if (ch == nil)
panic("close of nil channel"); panic("close of nil channel");
ch->close(); ch->close();
} }
...@@ -768,10 +769,10 @@ void _chan::close() { ...@@ -768,10 +769,10 @@ void _chan::close() {
// schedule: wake-up all readers // schedule: wake-up all readers
while (1) { while (1) {
_RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq); _RecvSendWaiting *recv = _dequeWaiter(&ch->_recvq);
if (recv == NULL) if (recv == nil)
break; break;
if (recv->pdata != NULL) if (recv->pdata != nil)
memset(recv->pdata, 0, ch->_elemsize); memset(recv->pdata, 0, ch->_elemsize);
wakeupv.push_back(recv); wakeupv.push_back(recv);
} }
...@@ -779,7 +780,7 @@ void _chan::close() { ...@@ -779,7 +780,7 @@ void _chan::close() {
// schedule: wake-up all writers (they will panic) // schedule: wake-up all writers (they will panic)
while (1) { while (1) {
_RecvSendWaiting *send = _dequeWaiter(&ch->_sendq); _RecvSendWaiting *send = _dequeWaiter(&ch->_sendq);
if (send == NULL) if (send == nil)
break; break;
wakeupv.push_back(send); wakeupv.push_back(send);
...@@ -793,7 +794,7 @@ void _chan::close() { ...@@ -793,7 +794,7 @@ void _chan::close() {
// len returns current number of buffered elements. // len returns current number of buffered elements.
unsigned _chanlen(_chan *ch) { unsigned _chanlen(_chan *ch) {
if (ch == NULL) if (ch == nil)
return 0; // len(nil) = 0 return 0; // len(nil) = 0
return ch->len(); return ch->len();
} }
...@@ -808,7 +809,7 @@ unsigned _chan::len() { ...@@ -808,7 +809,7 @@ unsigned _chan::len() {
// cap returns channel capacity. // cap returns channel capacity.
unsigned _chancap(_chan *ch) { unsigned _chancap(_chan *ch) {
if (ch == NULL) if (ch == nil)
return 0; // cap(nil) = 0 return 0; // cap(nil) = 0
return ch->cap(); return ch->cap();
} }
...@@ -834,7 +835,7 @@ void _chan::_dataq_append(const void *ptx) { ...@@ -834,7 +835,7 @@ void _chan::_dataq_append(const void *ptx) {
// _dataq_popleft pops oldest element from ch._dataq into *prx. // _dataq_popleft pops oldest element from ch._dataq into *prx.
// called with ch._mu locked. // called with ch._mu locked.
// if prx=NULL the element is popped, but not copied anywhere. // if prx=nil the element is popped, but not copied anywhere.
void _chan::_dataq_popleft(void *prx) { void _chan::_dataq_popleft(void *prx) {
_chan *ch = this; _chan *ch = this;
...@@ -843,7 +844,7 @@ void _chan::_dataq_popleft(void *prx) { ...@@ -843,7 +844,7 @@ void _chan::_dataq_popleft(void *prx) {
if (ch->_dataq_r >= ch->_cap) if (ch->_dataq_r >= ch->_cap)
bug("chan: dataq.popleft: r >= cap"); bug("chan: dataq.popleft: r >= cap");
if (prx != NULL) if (prx != nil)
memcpy(prx, &((char *)(ch+1))[ch->_dataq_r * ch->_elemsize], ch->_elemsize); memcpy(prx, &((char *)(ch+1))[ch->_dataq_r * ch->_elemsize], ch->_elemsize);
ch->_dataq_r++; ch->_dataq_r %= ch->_cap; ch->_dataq_r++; ch->_dataq_r %= ch->_cap;
ch->_dataq_n--; ch->_dataq_n--;
...@@ -855,13 +856,13 @@ void _chan::_dataq_popleft(void *prx) { ...@@ -855,13 +856,13 @@ void _chan::_dataq_popleft(void *prx) {
// _default represents default case for _select. // _default represents default case for _select.
static _selcase _mkdefault() { static _selcase _mkdefault() {
_selcase _ = { _selcase _ = {
.ch = NULL, .ch = nil,
.op = _DEFAULT, .op = _DEFAULT,
.flags = (_selflags)0, .flags = (_selflags)0,
.user = 0xff, .user = 0xff,
}; };
_ .ptxrx = NULL; _ .ptxrx = nil;
_ .rxok = NULL; _ .rxok = nil;
return _; return _;
} }
const _selcase _default = _mkdefault(); const _selcase _default = _mkdefault();
...@@ -933,7 +934,7 @@ int _chanselect(const _selcase *casev, int casec) { ...@@ -933,7 +934,7 @@ int _chanselect(const _selcase *casev, int casec) {
// send // send
else if (cas->op == _CHANSEND) { else if (cas->op == _CHANSEND) {
if (ch != NULL) { // nil chan is never ready if (ch != nil) { // nil chan is never ready
ch->_mu.lock(); ch->_mu.lock();
if (1) { if (1) {
bool done = ch->_trysend(cas->ptx()); bool done = ch->_trysend(cas->ptx());
...@@ -947,7 +948,7 @@ int _chanselect(const _selcase *casev, int casec) { ...@@ -947,7 +948,7 @@ int _chanselect(const _selcase *casev, int casec) {
// recv // recv
else if (cas->op == _CHANRECV) { else if (cas->op == _CHANRECV) {
if (ch != NULL) { // nil chan is never ready if (ch != nil) { // nil chan is never ready
// recv into inplace data is not supported // recv into inplace data is not supported
// ( in the future we might want to support it for symmetry with // ( in the future we might want to support it for symmetry with
// send, but it will requre to drop const from casev ) // send, but it will requre to drop const from casev )
...@@ -958,7 +959,7 @@ int _chanselect(const _selcase *casev, int casec) { ...@@ -958,7 +959,7 @@ int _chanselect(const _selcase *casev, int casec) {
if (1) { if (1) {
bool ok, done = ch->_tryrecv(cas->prx(), &ok); bool ok, done = ch->_tryrecv(cas->prx(), &ok);
if (done) { if (done) {
if (cas->rxok != NULL) if (cas->rxok != nil)
*cas->rxok = ok; *cas->rxok = ok;
return n; return n;
} }
...@@ -1016,7 +1017,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec, ...@@ -1016,7 +1017,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec,
for (i = 0; i < casec; i++) { for (i = 0; i < casec; i++) {
const _selcase *cas = &casev[i]; const _selcase *cas = &casev[i];
casev_onheap[i] = *cas; casev_onheap[i] = *cas;
if (cas->ch == NULL) // nil chan if (cas->ch == nil) // nil chan
continue; continue;
if (cas->op == _CHANSEND) { if (cas->op == _CHANSEND) {
if (!(cas->flags & _INPLACE_DATA)) if (!(cas->flags & _INPLACE_DATA))
...@@ -1032,7 +1033,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec, ...@@ -1032,7 +1033,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec,
// tx are appended sequentially; all rx go to &rxtxdata[0] // tx are appended sequentially; all rx go to &rxtxdata[0]
char *rxtxdata = (char *)malloc(max(rxmax, txtotal)); char *rxtxdata = (char *)malloc(max(rxmax, txtotal));
if (rxtxdata == NULL) if (rxtxdata == nil)
throw bad_alloc(); throw bad_alloc();
defer([&]() { defer([&]() {
free(rxtxdata); free(rxtxdata);
...@@ -1041,7 +1042,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec, ...@@ -1041,7 +1042,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec,
char *ptx = rxtxdata; char *ptx = rxtxdata;
for (i = 0; i <casec; i++) { for (i = 0; i <casec; i++) {
_selcase *cas = &casev_onheap[i]; _selcase *cas = &casev_onheap[i];
if (cas->ch == NULL) // nil chan if (cas->ch == nil) // nil chan
continue; continue;
if (cas->op == _CHANSEND) { if (cas->op == _CHANSEND) {
if (!(cas->flags & _INPLACE_DATA)) { if (!(cas->flags & _INPLACE_DATA)) {
...@@ -1066,7 +1067,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec, ...@@ -1066,7 +1067,7 @@ template<> int _chanselect2</*onstack=*/false>(const _selcase *casev, int casec,
_selcase *cas = &casev_onheap[selected]; _selcase *cas = &casev_onheap[selected];
if (cas->op == _CHANRECV) { if (cas->op == _CHANRECV) {
const _selcase *cas0 = &casev[selected]; const _selcase *cas0 = &casev[selected];
if (cas0->ptxrx != NULL) if (cas0->ptxrx != nil)
memcpy(cas0->ptxrx, cas->ptxrx, cas->ch->_elemsize); memcpy(cas0->ptxrx, cas->ptxrx, cas->ch->_elemsize);
} }
...@@ -1078,7 +1079,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv ...@@ -1078,7 +1079,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
// XXX or let caller stack-allocate? but then we force it to know sizeof(_RecvSendWaiting) // XXX or let caller stack-allocate? but then we force it to know sizeof(_RecvSendWaiting)
_RecvSendWaiting *waitv = (_RecvSendWaiting *)calloc(sizeof(_RecvSendWaiting), casec); _RecvSendWaiting *waitv = (_RecvSendWaiting *)calloc(sizeof(_RecvSendWaiting), casec);
int waitc = 0; int waitc = 0;
if (waitv == NULL) if (waitv == nil)
throw bad_alloc(); throw bad_alloc();
// on exit: remove all registered waiters from their wait queues. // on exit: remove all registered waiters from their wait queues.
defer([&]() { defer([&]() {
...@@ -1091,7 +1092,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv ...@@ -1091,7 +1092,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
bzero((void *)waitv, waitc*sizeof(waitv[0])); bzero((void *)waitv, waitc*sizeof(waitv[0]));
free(waitv); free(waitv);
waitv = NULL; waitv = nil;
}); });
...@@ -1099,14 +1100,14 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv ...@@ -1099,14 +1100,14 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
const _selcase *cas = &casev[n]; const _selcase *cas = &casev[n];
_chan *ch = cas->ch; _chan *ch = cas->ch;
if (ch == NULL) // nil chan is never ready if (ch == nil) // nil chan is never ready
continue; continue;
ch->_mu.lock(); ch->_mu.lock();
with_lock(g->_mu) { // with, because _trysend may panic with_lock(g->_mu) { // with, because _trysend may panic
// a case that we previously queued already won while we were // a case that we previously queued already won while we were
// queuing other cases. // queuing other cases.
if (g->which != NULL) { if (g->which != nil) {
ch->_mu.unlock(); ch->_mu.unlock();
goto wait_case_ready; goto wait_case_ready;
} }
...@@ -1115,7 +1116,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv ...@@ -1115,7 +1116,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
if (cas->op == _CHANSEND) { if (cas->op == _CHANSEND) {
bool done = ch->_trysend(cas->ptx()); bool done = ch->_trysend(cas->ptx());
if (done) { if (done) {
g->which = &_sel_txrx_prepoll_won; // !NULL not to let already queued cases win g->which = &_sel_txrx_prepoll_won; // !nil not to let already queued cases win
return n; return n;
} }
...@@ -1135,8 +1136,8 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv ...@@ -1135,8 +1136,8 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
else if (cas->op == _CHANRECV) { else if (cas->op == _CHANRECV) {
bool ok, done = ch->_tryrecv(cas->prx(), &ok); bool ok, done = ch->_tryrecv(cas->prx(), &ok);
if (done) { if (done) {
g->which = &_sel_txrx_prepoll_won; // !NULL not to let already queued cases win g->which = &_sel_txrx_prepoll_won; // !nil not to let already queued cases win
if (cas->rxok != NULL) if (cas->rxok != nil)
*cas->rxok = ok; *cas->rxok = ok;
return n; return n;
} }
...@@ -1176,7 +1177,7 @@ wait_case_ready: ...@@ -1176,7 +1177,7 @@ wait_case_ready:
return selected; return selected;
} }
else if (cas->op == _CHANRECV) { else if (cas->op == _CHANRECV) {
if (cas->rxok != NULL) if (cas->rxok != nil)
*cas->rxok = sel->ok; *cas->rxok = sel->ok;
return selected; return selected;
} }
...@@ -1185,9 +1186,9 @@ wait_case_ready: ...@@ -1185,9 +1186,9 @@ wait_case_ready:
} }
// _blockforever blocks current goroutine forever. // _blockforever blocks current goroutine forever.
void (*_tblockforever)() = NULL; void (*_tblockforever)() = nil;
void _blockforever() { void _blockforever() {
if (_tblockforever != NULL) if (_tblockforever != nil)
_tblockforever(); _tblockforever();
// take a lock twice. It will forever block on the second lock attempt. // take a lock twice. It will forever block on the second lock attempt.
// Under gevent, similarly to Go, this raises "LoopExit: This operation // Under gevent, similarly to Go, this raises "LoopExit: This operation
...@@ -1261,10 +1262,15 @@ double now() { ...@@ -1261,10 +1262,15 @@ double now() {
// ---- misc ---- // ---- misc ----
// golang::
namespace golang {
// zalloc allocates zeroed memory. // zalloc allocates zeroed memory.
static void *zalloc(size_t size) { static void *zalloc(size_t size) {
void *mem = malloc(size); void *mem = malloc(size);
if (mem != NULL) if (mem != nil)
memset(mem, 0, size); memset(mem, 0, size);
return mem; return mem;
} }
} // golang::
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -46,14 +46,14 @@ using std::vector; ...@@ -46,14 +46,14 @@ using std::vector;
// verify chan<T> automatic reference counting. // verify chan<T> automatic reference counting.
void _test_chan_cpp_refcount() { void _test_chan_cpp_refcount() {
chan<int> ch; chan<int> ch;
ASSERT(ch == NULL); ASSERT(ch == nil);
ASSERT(!(ch != NULL)); ASSERT(!(ch != nil));
ASSERT(ch._rawchan() == NULL); ASSERT(ch._rawchan() == nil);
ch = makechan<int>(); ch = makechan<int>();
ASSERT(!(ch == NULL)); ASSERT(!(ch == nil));
ASSERT(ch != NULL); ASSERT(ch != nil);
ASSERT(ch._rawchan() != NULL); ASSERT(ch._rawchan() != nil);
_chan *_ch = ch._rawchan(); _chan *_ch = ch._rawchan();
ASSERT(_chanrefcnt(_ch) == 1); ASSERT(_chanrefcnt(_ch) == 1);
...@@ -71,8 +71,8 @@ void _test_chan_cpp_refcount() { ...@@ -71,8 +71,8 @@ void _test_chan_cpp_refcount() {
// copy = // copy =
{ {
chan<int> ch2; chan<int> ch2;
ASSERT(ch2 == NULL); ASSERT(ch2 == nil);
ASSERT(ch2._rawchan() == NULL); ASSERT(ch2._rawchan() == nil);
ch2 = ch; ch2 = ch;
ASSERT(ch2._rawchan() == _ch); ASSERT(ch2._rawchan() == _ch);
...@@ -80,9 +80,9 @@ void _test_chan_cpp_refcount() { ...@@ -80,9 +80,9 @@ void _test_chan_cpp_refcount() {
ASSERT(ch2 == ch); ASSERT(ch2 == ch);
ASSERT(!(ch2 != ch)); ASSERT(!(ch2 != ch));
ch2 = NULL; ch2 = nil;
ASSERT(ch2 == NULL); ASSERT(ch2 == nil);
ASSERT(ch2._rawchan() == NULL); ASSERT(ch2._rawchan() == nil);
ASSERT(_chanrefcnt(_ch) == 1); ASSERT(_chanrefcnt(_ch) == 1);
ASSERT(!(ch2 == ch)); ASSERT(!(ch2 == ch));
ASSERT(ch2 != ch); ASSERT(ch2 != ch);
...@@ -91,18 +91,18 @@ void _test_chan_cpp_refcount() { ...@@ -91,18 +91,18 @@ void _test_chan_cpp_refcount() {
// move ctor // move ctor
chan<int> ch2(move(ch)); chan<int> ch2(move(ch));
ASSERT(ch == NULL); ASSERT(ch == nil);
ASSERT(ch._rawchan() == NULL); ASSERT(ch._rawchan() == nil);
ASSERT(ch2 != NULL); ASSERT(ch2 != nil);
ASSERT(ch2._rawchan() == _ch); ASSERT(ch2._rawchan() == _ch);
ASSERT(_chanrefcnt(_ch) == 1); ASSERT(_chanrefcnt(_ch) == 1);
// move = // move =
ch = move(ch2); ch = move(ch2);
ASSERT(ch != NULL); ASSERT(ch != nil);
ASSERT(ch._rawchan() == _ch); ASSERT(ch._rawchan() == _ch);
ASSERT(ch2 == NULL); ASSERT(ch2 == nil);
ASSERT(ch2._rawchan() == NULL); ASSERT(ch2._rawchan() == nil);
ASSERT(_chanrefcnt(_ch) == 1); ASSERT(_chanrefcnt(_ch) == 1);
// ch goes out of scope and destroys raw channel // ch goes out of scope and destroys raw channel
...@@ -117,7 +117,7 @@ struct Point { ...@@ -117,7 +117,7 @@ struct Point {
void _test_chan_cpp() { void _test_chan_cpp() {
chan<structZ> done = makechan<structZ>(); chan<structZ> done = makechan<structZ>();
chan<int> chi = makechan<int>(1); chan<int> chi = makechan<int>(1);
chan<Point> chp = makechan<Point>(); chp = NULL; chan<Point> chp = makechan<Point>(); chp = nil;
int i, j, _; int i, j, _;
Point p; Point p;
...@@ -155,7 +155,7 @@ void _test_chan_cpp() { ...@@ -155,7 +155,7 @@ void _test_chan_cpp() {
// waitBlocked waits until at least nrx recv and ntx send operations block // waitBlocked waits until at least nrx recv and ntx send operations block
// waiting on the channel. // waiting on the channel.
void waitBlocked(_chan *ch, int nrx, int ntx) { void waitBlocked(_chan *ch, int nrx, int ntx) {
if (ch == NULL) if (ch == nil)
panic("wait blocked: called on nil channel"); panic("wait blocked: called on nil channel");
double t0 = time::now(); double t0 = time::now();
...@@ -308,12 +308,12 @@ void __test_close_wakeup_all(bool vs_select) { ...@@ -308,12 +308,12 @@ void __test_close_wakeup_all(bool vs_select) {
// as other workers vvv don't use ch after wakeup from ch.recv(). // as other workers vvv don't use ch after wakeup from ch.recv().
if (!vs_select) if (!vs_select)
ASSERT(_chanrefcnt(ch._rawchan()) == 1); ASSERT(_chanrefcnt(ch._rawchan()) == 1);
ch = NULL; ch = nil;
done.send(structZ{}); done.send(structZ{});
}); });
waitBlocked(_ch, /*nrx=*/1, /*ntx=*/0); waitBlocked(_ch, /*nrx=*/1, /*ntx=*/0);
ASSERT(_chanrefcnt(_ch) == 2); ASSERT(_chanrefcnt(_ch) == 2);
ch = NULL; ch = nil;
ASSERT(_chanrefcnt(_ch) == 1); ASSERT(_chanrefcnt(_ch) == 1);
// many other ch.recv or select({ch.recv}) subscribers queued to ch.recvq // many other ch.recv or select({ch.recv}) subscribers queued to ch.recvq
...@@ -321,7 +321,7 @@ void __test_close_wakeup_all(bool vs_select) { ...@@ -321,7 +321,7 @@ void __test_close_wakeup_all(bool vs_select) {
for (i=0; i < N; i++) { for (i=0; i < N; i++) {
go([_ch, done, vs_select]() { go([_ch, done, vs_select]() {
if (!vs_select) { if (!vs_select) {
_chanrecv(_ch, NULL); _chanrecv(_ch, nil);
} else { } else {
int rx; int rx;
select({ select({
...@@ -363,7 +363,7 @@ void __test_select_win_while_queue() { ...@@ -363,7 +363,7 @@ void __test_select_win_while_queue() {
Data *data_send = (Data *)calloc(1, sizeof(Data)); Data *data_send = (Data *)calloc(1, sizeof(Data));
Data *data_recv = (Data *)calloc(1, sizeof(Data)); Data *data_recv = (Data *)calloc(1, sizeof(Data));
if (data_send == NULL || data_recv == NULL) if (data_send == nil || data_recv == nil)
throw std::bad_alloc(); throw std::bad_alloc();
for (i=0; i<Ndata; i++) for (i=0; i<Ndata; i++)
data_send->_[i] = i % 0xff; data_send->_[i] = i % 0xff;
...@@ -407,7 +407,7 @@ void _test_select_inplace() { ...@@ -407,7 +407,7 @@ void _test_select_inplace() {
// inplace tx // inplace tx
go([ch]() { go([ch]() {
_selcase sel[1]; _selcase sel[1];
sel[0] = ch.sends(NULL); sel[0] = ch.sends(nil);
*(int *)&sel[0].itxrx = 12345; *(int *)&sel[0].itxrx = 12345;
sel[0].flags = _INPLACE_DATA; sel[0].flags = _INPLACE_DATA;
int _ = select(sel); int _ = select(sel);
...@@ -421,34 +421,34 @@ void _test_select_inplace() { ...@@ -421,34 +421,34 @@ void _test_select_inplace() {
_selcase sel[1]; _selcase sel[1];
sel[0] = ch.recvs(); sel[0] = ch.recvs();
sel[0].flags = _INPLACE_DATA; sel[0].flags = _INPLACE_DATA;
const char *err = NULL; const char *err = nil;
try { try {
select(sel); select(sel);
} catch (...) { } catch (...) {
err = recover(); err = recover();
} }
ASSERT(err != NULL); ASSERT(err != nil);
ASSERT(!strcmp(err, "select: recv into inplace data")); ASSERT(!strcmp(err, "select: recv into inplace data"));
// _selcase ptx/prx // _selcase ptx/prx
_selcase cas = _default; _selcase cas = _default;
err = NULL; err = nil;
try { try {
cas.ptx(); cas.ptx();
} catch (...) { } catch (...) {
err = recover(); err = recover();
} }
ASSERT(err != NULL); ASSERT(err != nil);
ASSERT(!strcmp(err, "_selcase: ptx: op != send")); ASSERT(!strcmp(err, "_selcase: ptx: op != send"));
err = NULL; err = nil;
try { try {
cas.prx(); cas.prx();
} catch (...) { } catch (...) {
err = recover(); err = recover();
} }
ASSERT(err != NULL); ASSERT(err != nil);
ASSERT(!strcmp(err, "_selcase: prx: op != recv")); ASSERT(!strcmp(err, "_selcase: prx: op != recv"));
cas = ch.sends(&i); cas = ch.sends(&i);
...@@ -459,13 +459,13 @@ void _test_select_inplace() { ...@@ -459,13 +459,13 @@ void _test_select_inplace() {
cas = ch.recvs(&i); cas = ch.recvs(&i);
ASSERT(cas.prx() == &i); ASSERT(cas.prx() == &i);
cas.flags = _INPLACE_DATA; cas.flags = _INPLACE_DATA;
err = NULL; err = nil;
try { try {
cas.prx(); cas.prx();
} catch (...) { } catch (...) {
err = recover(); err = recover();
} }
ASSERT(err != NULL); ASSERT(err != nil);
ASSERT(!strcmp(err, "_selcase: prx: recv with inplace data")); ASSERT(!strcmp(err, "_selcase: prx: recv with inplace data"));
} }
...@@ -501,9 +501,9 @@ public: ...@@ -501,9 +501,9 @@ public:
void _test_refptr() { void _test_refptr() {
refptr<MyObj> p; refptr<MyObj> p;
ASSERT(p == NULL); ASSERT(p == nil);
ASSERT(!(p != NULL)); ASSERT(!(p != nil));
ASSERT(p._ptr() == NULL); ASSERT(p._ptr() == nil);
MyObj *obj = new MyObj(); MyObj *obj = new MyObj();
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
...@@ -551,8 +551,8 @@ void _test_refptr() { ...@@ -551,8 +551,8 @@ void _test_refptr() {
{ {
refptr<MyObj> q; refptr<MyObj> q;
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
ASSERT(q == NULL); ASSERT(q == nil);
ASSERT(q._ptr() == NULL); ASSERT(q._ptr() == nil);
ASSERT(!(p == q)); ASSERT(!(p == q));
ASSERT(p != q); ASSERT(p != q);
...@@ -563,10 +563,10 @@ void _test_refptr() { ...@@ -563,10 +563,10 @@ void _test_refptr() {
ASSERT(p == q); ASSERT(p == q);
ASSERT(!(p != q)); ASSERT(!(p != q));
q = NULL; q = nil;
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
ASSERT(p._ptr() == obj); ASSERT(p._ptr() == obj);
ASSERT(q._ptr() == NULL); ASSERT(q._ptr() == nil);
ASSERT(!(p == q)); ASSERT(!(p == q));
ASSERT(p != q); ASSERT(p != q);
} }
...@@ -575,34 +575,34 @@ void _test_refptr() { ...@@ -575,34 +575,34 @@ void _test_refptr() {
// move ctor // move ctor
refptr<MyObj> q(move(p)); refptr<MyObj> q(move(p));
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
ASSERT(p == NULL); ASSERT(p == nil);
ASSERT(p._ptr() == NULL); ASSERT(p._ptr() == nil);
ASSERT(q != NULL); ASSERT(q != nil);
ASSERT(q._ptr() == obj); ASSERT(q._ptr() == obj);
// move = // move =
p = move(q); p = move(q);
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
ASSERT(p != NULL); ASSERT(p != nil);
ASSERT(p._ptr() == obj); ASSERT(p._ptr() == obj);
ASSERT(q == NULL); ASSERT(q == nil);
ASSERT(q._ptr() == NULL); ASSERT(q._ptr() == nil);
// p goes out of scope and destroys obj // p goes out of scope and destroys obj
} }
void _test_global() { void _test_global() {
global<refptr<MyObj>> g; global<refptr<MyObj>> g;
ASSERT(g == NULL); ASSERT(g == nil);
ASSERT(!(g != NULL)); ASSERT(!(g != nil));
ASSERT(g._ptr() == NULL); ASSERT(g._ptr() == nil);
MyObj *obj = new MyObj(); MyObj *obj = new MyObj();
refptr<MyObj> p = adoptref(obj); refptr<MyObj> p = adoptref(obj);
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
obj->i = 3; obj->i = 3;
ASSERT(g._ptr() == NULL); ASSERT(g._ptr() == nil);
ASSERT(p._ptr() == obj); ASSERT(p._ptr() == obj);
ASSERT(!(g == p)); ASSERT(!(g == p));
ASSERT(!(p == g)); ASSERT(!(p == g));
...@@ -614,8 +614,8 @@ void _test_global() { ...@@ -614,8 +614,8 @@ void _test_global() {
ASSERT(obj->refcnt() == 2); ASSERT(obj->refcnt() == 2);
ASSERT(g._ptr() == obj); ASSERT(g._ptr() == obj);
ASSERT(p._ptr() == obj); ASSERT(p._ptr() == obj);
ASSERT(!(g == NULL)); ASSERT(!(g == nil));
ASSERT(g != NULL); ASSERT(g != nil);
ASSERT(g == p); ASSERT(g == p);
ASSERT(p == g); ASSERT(p == g);
ASSERT(!(g != p)); ASSERT(!(g != p));
...@@ -630,15 +630,15 @@ void _test_global() { ...@@ -630,15 +630,15 @@ void _test_global() {
// global = nil - obj reference is released // global = nil - obj reference is released
ASSERT(obj->refcnt() == 2); ASSERT(obj->refcnt() == 2);
g = NULL; g = nil;
ASSERT(obj->refcnt() == 1); ASSERT(obj->refcnt() == 1);
ASSERT(g._ptr() == NULL); ASSERT(g._ptr() == nil);
// copy ctor global <- refptr // copy ctor global <- refptr
{ {
global<refptr<MyObj>> h(p); global<refptr<MyObj>> h(p);
ASSERT(obj->refcnt() == 2); ASSERT(obj->refcnt() == 2);
ASSERT(g._ptr() == NULL); ASSERT(g._ptr() == nil);
ASSERT(h._ptr() == obj); ASSERT(h._ptr() == obj);
ASSERT(p._ptr() == obj); ASSERT(p._ptr() == obj);
ASSERT(!(h == g)); ASSERT(!(h == g));
......
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -39,8 +39,8 @@ namespace runtime { ...@@ -39,8 +39,8 @@ namespace runtime {
// pyexited indicates whether Python interpreter exited. // pyexited indicates whether Python interpreter exited.
static sync::Mutex *pyexitedMu = NULL; // allocated in _init and never freed not to race static sync::Mutex *pyexitedMu = nil; // allocated in _init and never freed not to race
static sync::WaitGroup *pygilTaking = NULL; // at exit on dtor vs use. static sync::WaitGroup *pygilTaking = nil; // at exit on dtor vs use.
static bool pyexited = false; static bool pyexited = false;
void _init() { void _init() {
...@@ -102,8 +102,8 @@ error PyErr_Fetch() { ...@@ -102,8 +102,8 @@ error PyErr_Fetch() {
PyGILState_Release(gstate); PyGILState_Release(gstate);
// no error // no error
if (pyexc_type == NULL && pyexc_value == NULL && pyexc_tb == NULL) if (pyexc_type == nil && pyexc_value == nil && pyexc_tb == nil)
return NULL; return nil;
// -> _PyError // -> _PyError
_PyError* _e = new _PyError(); _PyError* _e = new _PyError();
...@@ -141,9 +141,9 @@ _PyError::~_PyError() { ...@@ -141,9 +141,9 @@ _PyError::~_PyError() {
PyObject *pyexc_type = this->pyexc_type; PyObject *pyexc_type = this->pyexc_type;
PyObject *pyexc_value = this->pyexc_value; PyObject *pyexc_value = this->pyexc_value;
PyObject *pyexc_tb = this->pyexc_tb; PyObject *pyexc_tb = this->pyexc_tb;
this->pyexc_type = NULL; this->pyexc_type = nil;
this->pyexc_value = NULL; this->pyexc_value = nil;
this->pyexc_tb = NULL; this->pyexc_tb = nil;
if (!ok) { if (!ok) {
return; return;
} }
...@@ -182,7 +182,7 @@ PyFunc::PyFunc(const PyFunc& from) { ...@@ -182,7 +182,7 @@ PyFunc::PyFunc(const PyFunc& from) {
tie(gstate, ok) = pygil_ensure(); tie(gstate, ok) = pygil_ensure();
if (!ok) { if (!ok) {
pyf = NULL; // won't be used pyf = nil; // won't be used
return; return;
} }
...@@ -197,7 +197,7 @@ PyFunc::~PyFunc() { ...@@ -197,7 +197,7 @@ PyFunc::~PyFunc() {
tie(gstate, ok) = pygil_ensure(); tie(gstate, ok) = pygil_ensure();
PyObject *pyf = this->pyf; PyObject *pyf = this->pyf;
this->pyf = NULL; this->pyf = nil;
if (!ok) { if (!ok) {
return; return;
} }
...@@ -222,8 +222,8 @@ error PyFunc::operator() () const { ...@@ -222,8 +222,8 @@ error PyFunc::operator() () const {
} }
error err; error err;
PyObject *ret = PyObject_CallFunction(pyf, NULL); PyObject *ret = PyObject_CallFunction(pyf, nil);
if (ret == NULL) { if (ret == nil) {
err = PyErr_Fetch(); err = PyErr_Fetch();
} }
Py_XDECREF(ret); Py_XDECREF(ret);
......
// Copyright (C) 2018-2019 Nexedi SA and Contributors. // Copyright (C) 2018-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -84,13 +84,13 @@ void WaitGroup::add(int delta) { ...@@ -84,13 +84,13 @@ void WaitGroup::add(int delta) {
void WaitGroup::wait() { void WaitGroup::wait() {
WaitGroup& wg = *this; WaitGroup& wg = *this;
chan<structZ> done = NULL; chan<structZ> done = nil;
wg._mu.lock(); wg._mu.lock();
if (wg._count != 0) if (wg._count != 0)
done = wg._done; done = wg._done;
wg._mu.unlock(); wg._mu.unlock();
if (done == NULL) // wg._count was =0 if (done == nil) // wg._count was =0
return; return;
done.recv(); done.recv();
...@@ -123,7 +123,7 @@ void _WorkGroup::go(func<error(context::Context)> f) { ...@@ -123,7 +123,7 @@ void _WorkGroup::go(func<error(context::Context)> f) {
}); });
error err = f(g->_ctx); // TODO consider also propagating panic error err = f(g->_ctx); // TODO consider also propagating panic
if (err == NULL) if (err == nil)
return; return;
g->_mu.lock(); g->_mu.lock();
...@@ -131,7 +131,7 @@ void _WorkGroup::go(func<error(context::Context)> f) { ...@@ -131,7 +131,7 @@ void _WorkGroup::go(func<error(context::Context)> f) {
g->_mu.unlock(); g->_mu.unlock();
}); });
if (g->_err == NULL) { if (g->_err == nil) {
// this goroutine is the first failed task // this goroutine is the first failed task
g->_err = err; g->_err = err;
g->_cancel(); g->_cancel();
......
// Copyright (C) 2019 Nexedi SA and Contributors. // Copyright (C) 2019-2020 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com> // Kirill Smelkov <kirr@nexedi.com>
// //
// This program is free software: you can Use, Study, Modify and Redistribute // This program is free software: you can Use, Study, Modify and Redistribute
...@@ -39,7 +39,7 @@ Timer _new_timer(double dt, func<void()>); ...@@ -39,7 +39,7 @@ Timer _new_timer(double dt, func<void()>);
chan<double> tick(double dt) { chan<double> tick(double dt) {
if (dt <= 0) if (dt <= 0)
return NULL; return nil;
return new_ticker(dt)->c; return new_ticker(dt)->c;
} }
...@@ -120,7 +120,7 @@ void _Timer::decref() { ...@@ -120,7 +120,7 @@ void _Timer::decref() {
Timer _new_timer(double dt, func<void()> f) { Timer _new_timer(double dt, func<void()> f) {
Timer t = adoptref(new _Timer()); Timer t = adoptref(new _Timer());
t->c = (f == NULL ? makechan<double>(1) : NULL); t->c = (f == nil ? makechan<double>(1) : nil);
t->_f = f; t->_f = f;
t->_dt = INFINITY; t->_dt = INFINITY;
t->_ver = 0; t->_ver = 0;
...@@ -129,7 +129,7 @@ Timer _new_timer(double dt, func<void()> f) { ...@@ -129,7 +129,7 @@ Timer _new_timer(double dt, func<void()> f) {
} }
Timer new_timer(double dt) { Timer new_timer(double dt) {
return _new_timer(dt, NULL); return _new_timer(dt, nil);
} }
bool _Timer::stop() { bool _Timer::stop() {
...@@ -186,7 +186,7 @@ void _Timer::_fire(double dt, int ver) { ...@@ -186,7 +186,7 @@ void _Timer::_fire(double dt, int ver) {
// send under ._mu so that .stop can be sure that if it sees // send under ._mu so that .stop can be sure that if it sees
// ._dt = INFINITY, there is no ongoing .c send. // ._dt = INFINITY, there is no ongoing .c send.
if (t._f == NULL) { if (t._f == nil) {
t.c.send(now()); t.c.send(now());
t._mu.unlock(); t._mu.unlock();
return; return;
......
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