Skip to content
Snippets Groups Projects
Commit af311e35 authored by Stephen R. van den Berg's avatar Stephen R. van den Berg
Browse files

Thread.ResourceCount: New module to implement resource counters.

parent 356f7e13
No related branches found
No related tags found
No related merge requests found
......@@ -804,6 +804,79 @@ optional class Farm
}
}
//! When this key is destroyed, the corresponding resource counter
//! will be decremented.
//!
//! @seealso
//! @[ResourceCount], @[MutexKey]
//!
optional class ResourceCountKey {
/*semi*/private ResourceCount parent;
/*semi*/private void create(ResourceCount _parent) {
parent = _parent;
}
/*semi*/private void destroy() {
--parent->_count;
parent->_cond->signal();
}
}
//! Implements an inverted-semaphore-like resource
//! counter. A thread can poll or perform a blocking wait for the
//! resource-count to drop below a certain @ref{level@}.
//!
//! @seealso
//! @[ResourceCountKey], @[Condition], @[Mutex]
optional class ResourceCount {
/*semi*/final int _count;
/*semi*/final Condition _cond = Condition();
//! @param level
//! The maximum level that is considered drained.
//!
//! @returns
//! True if the resource counter drops to equal or below @ref{level@}.
/*semi*/final int(0..1) drained(void|int level) {
return level >= _count;
}
//! Blocks until the resource-counter dips to max @ref{level@}.
//!
//! @param lock
//! A previously acquired @[MutexKey].
//!
//! @param level
//! The maximum level that is considered drained.
/*semi*/final void wait_till_drained(MutexKey lock, void|int level) {
while (_count > level) // Recheck before allowing further
_cond->wait(lock);
lock = 0; // Eliminate references
}
//! Increments the resource-counter.
//! @returns
//! A @[ResourceCountKey] to decrement the resource-counter again.
/*semi*/final ResourceCountKey acquire() {
_count++;
return ResourceCountKey(this);
}
/*semi*/private string _sprintf(int type) {
string res = UNDEFINED;
switch(type) {
case 'O':
res = sprintf("Count: %d", _count);
break;
case 'd':
res = sprintf("%d", _count);
break;
}
return res;
}
}
#else /* !constant(thread_create) */
// Simulations of some of the classes for nonthreaded use.
......
......@@ -1743,6 +1743,22 @@ test_false([[ TestQueue->size() ]])
test_true([[ zero_type(TestQueue->try_read()) ]])
test_do([[ add_constant("TestQueue"); ]])
// Thread.ResourceCount
test_do([[ add_constant("TestResourceCount", Thread.ResourceCount()); ]])
test_any_equal([[
int i;
array a = allocate(10);
for(i = 0; i < 10; i++) {
a[i] = TestResourceCount->acquire();
}
for(i = 0; i < 10; i++) {
a[i] = 0;
a[i] = TestResourceCount->drained();
}
return a;
]], ({ 0,0,0,0,0,0,0,0,0,1 }))
test_do([[ add_constant("TestResourceCount"); ]])
test_false(!Val.true)
test_true(!Val.false)
test_eq((int) Val.true, 1)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment