Commit e614d641 authored by Kirill Smelkov's avatar Kirill Smelkov

libgolang: Switch _chan refcounting to refobj

Refobj was just added in previous patch as the class that provides base
functionality for reference-counted objects.
parent e82b4fab
...@@ -251,8 +251,7 @@ struct _RecvSendWaiting; ...@@ -251,8 +251,7 @@ struct _RecvSendWaiting;
// //
// (*) for example "thread" runtime works without GIL, while "gevent" runtime // (*) for example "thread" runtime works without GIL, while "gevent" runtime
// acquires GIL on every semaphore acquire. // acquires GIL on every semaphore acquire.
struct _chan { struct _chan : refobj {
atomic<int> _refcnt; // reference counter for _chan object
unsigned _cap; // channel capacity (in elements) unsigned _cap; // channel capacity (in elements)
unsigned _elemsize; // size of element unsigned _elemsize; // size of element
...@@ -266,9 +265,7 @@ struct _chan { ...@@ -266,9 +265,7 @@ struct _chan {
unsigned _dataq_r; // index for next read (in elements; can be used only if _dataq_n > 0) unsigned _dataq_r; // index for next read (in elements; can be used only if _dataq_n > 0)
unsigned _dataq_w; // index for next write (in elements; can be used only if _dataq_n < _cap) unsigned _dataq_w; // index for next write (in elements; can be used only if _dataq_n < _cap)
void incref();
void decref(); void decref();
int refcnt();
void send(const void *ptx); void send(const void *ptx);
bool recv_(void *prx); bool recv_(void *prx);
...@@ -289,6 +286,9 @@ private: ...@@ -289,6 +286,9 @@ private:
void __send2 (const void *, _WaitGroup*, _RecvSendWaiting*); void __send2 (const void *, _WaitGroup*, _RecvSendWaiting*);
template<bool onstack> bool _recv2_(void *); template<bool onstack> bool _recv2_(void *);
bool __recv2_(void *, _WaitGroup*, _RecvSendWaiting*); bool __recv2_(void *, _WaitGroup*, _RecvSendWaiting*);
friend _chan *_makechan(unsigned elemsize, unsigned size);
_chan() {}; // used by _makechan to init _mu, refobj, ...
}; };
// _RecvSendWaiting represents a receiver/sender waiting on a chan. // _RecvSendWaiting represents a receiver/sender waiting on a chan.
...@@ -439,9 +439,8 @@ _chan *_makechan(unsigned elemsize, unsigned size) { ...@@ -439,9 +439,8 @@ _chan *_makechan(unsigned elemsize, unsigned size) {
ch = (_chan *)zalloc(sizeof(_chan) + size*elemsize); ch = (_chan *)zalloc(sizeof(_chan) + size*elemsize);
if (ch == NULL) if (ch == NULL)
panic("makechan: alloc failed"); panic("makechan: alloc failed");
new (&ch->_mu) sync::Mutex(); new (ch) _chan(); // init .refobj, ._mu, ...
ch->_refcnt = 1;
ch->_cap = size; ch->_cap = size;
ch->_elemsize = elemsize; ch->_elemsize = elemsize;
ch->_closed = false; ch->_closed = false;
...@@ -469,13 +468,6 @@ void _chanxincref(_chan *ch) { ...@@ -469,13 +468,6 @@ void _chanxincref(_chan *ch) {
return; return;
ch->incref(); ch->incref();
} }
void _chan::incref() {
_chan *ch = this;
int refcnt_was = ch->_refcnt.fetch_add(+1);
if (refcnt_was < 1)
panic("chan: incref: refcnt was < 1");
}
// _chanxdecref decrements reference counter of the channel. // _chanxdecref decrements reference counter of the channel.
// //
...@@ -489,10 +481,7 @@ void _chanxdecref(_chan *ch) { ...@@ -489,10 +481,7 @@ void _chanxdecref(_chan *ch) {
void _chan::decref() { void _chan::decref() {
_chan *ch = this; _chan *ch = this;
int refcnt_was = ch->_refcnt.fetch_add(-1); if (!ch->__decref())
if (refcnt_was < 1)
panic("chan: decref: refcnt was < 1");
if (refcnt_was != 1)
return; return;
// refcnt=0 -> free the channel // refcnt=0 -> free the channel
...@@ -512,10 +501,6 @@ void _chan::decref() { ...@@ -512,10 +501,6 @@ void _chan::decref() {
int _chanrefcnt(_chan *ch) { int _chanrefcnt(_chan *ch) {
return ch->refcnt(); return ch->refcnt();
} }
int _chan::refcnt() {
_chan *ch = this;
return ch->_refcnt;
}
void _blockforever(); void _blockforever();
......
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