Skip to content
Snippets Groups Projects
Commit c240daa3 authored by Avi Kivity's avatar Avi Kivity
Browse files

semaphore: add support for multiple units in wait() and post()

Use Nadav's idea of iterating over the list and selecting wait records
that fit the available units.
parent 747ff478
No related branches found
No related tags found
No related merge requests found
......@@ -6,34 +6,35 @@ semaphore::semaphore(unsigned val)
{
}
void semaphore::post()
void semaphore::post(unsigned units)
{
auto wr = with_lock(*_mtx, [this] () -> wait_record* {
if (_waiters.empty()) {
++_val;
return nullptr;
with_lock(*_mtx, [=] {
_val += units;
auto i = _waiters.begin();
while (_val > 0 && i != _waiters.end()) {
auto p = i++;
auto& wr = *p;
if (wr->units <= _val) {
_val -= wr->units;
wr->owner->wake();
wr->owner = nullptr;
_waiters.erase(p);
}
}
auto wr = _waiters.front();
_waiters.pop_front();
return wr;
});
if (wr) {
auto t = wr->owner;
wr->owner = nullptr;
t->wake();
}
}
void semaphore::wait()
void semaphore::wait(unsigned units)
{
bool wait = false;
wait_record wr;
wr.owner = nullptr;
with_lock(*_mtx, [&] {
if (_val > 0) {
--_val;
if (_val >= units) {
_val -= units;
} else {
wr.owner = sched::thread::current();
wr.units = units;
_waiters.push_back(&wr);
wait = true;
}
......@@ -43,12 +44,12 @@ void semaphore::wait()
sched::thread::wait_until([&] { return !wr.owner; });
}
bool semaphore::trywait()
bool semaphore::trywait(unsigned units)
{
bool ok = false;
with_lock(*_mtx, [&] {
if (_val > 0) {
--_val;
if (_val > units) {
_val -= units;
ok = true;
}
});
......
......@@ -9,14 +9,15 @@
class semaphore {
public:
explicit semaphore(unsigned val);
void post();
void wait();
bool trywait();
void post(unsigned units = 1);
void wait(unsigned units = 1);
bool trywait(unsigned units = 1);
private:
unsigned _val;
std::unique_ptr<mutex> _mtx;
struct wait_record {
sched::thread* owner;
unsigned units;
};
std::list<wait_record*> _waiters;
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment