Commit 78e38690 authored by Kirill Smelkov's avatar Kirill Smelkov

libgolang: Clarify with_lock wrt covered scope

Make it clear which scope is covered by with_lock(mu): instead of
implicitly having it from with_lock till end of current block

		with_lock(mu);
		...
	} // end of current block

make it to be the statement covered by with_lock, as if with_lock was
e.g. an `if`, for example:

	with_lock(mu)
		do_something();
	// mu released here

or

	with_lock(mu) {
		do_smth1();
		do_smth2();
	} // mu released here

This makes the intent in __chanselect2 more clear: it was

	ch->_mu.lock();
	with_lock(g->_mu);
		...
	ch->_mu.unlock();

and semantically human expects g->mu to be released _before_
ch->_mu.unlock(). However with current with_lock implementation, g->mu
will be released _after_ ch->_mu.unlock(), which goes against intuition.

-> By reworking with_lock implementation to cover only next statement or
block of code we make sure that g->_mu will be released _before_
ch->_mu - the same way as it was until 3b241983 (Port/move channels to
C/C++/Pyx):

	ch->_mu.lock();
	with_lock(g->_mu) {
		...
	}
	ch->_mu.unlock();
parent 5d72c88c
......@@ -183,7 +183,22 @@ private:
};
// with_lock mimics `with mu` from python.
#define with_lock(mu) std::lock_guard<Mutex> _with_lock_ ## __COUNTER__ (mu)
// usage example:
//
// with_lock(mu) {
// ...
// }
#define with_lock(mu) for ( \
_with_lock_guard _with_lock(mu); \
_with_lock.once(); \
)
struct _with_lock_guard {
std::lock_guard<Mutex> mug;
bool done;
_with_lock_guard(Mutex &mu) : mug(mu), done(false) {}
bool once() { bool _ = !done; done = true; return _; }
};
// defer(f) mimics defer from golang.
// XXX f is called at end of current scope, not function.
......@@ -1013,7 +1028,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
continue;
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
// queuing other cases.
if (g->which != NULL) {
......@@ -1067,6 +1082,7 @@ static int __chanselect2(const _selcase *casev, int casec, const vector<int>& nv
else {
bug("select: invalid op during phase 2");
}
}
ch->_mu.unlock();
}
......
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