* Added support for timeouts.

* Added support for non-published condition variables. One has to call
  Init() on those, and add entries directly with the
  ConditionVariable::Add() method.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25110 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2008-04-22 21:46:23 +00:00
parent f842b6fa57
commit 023bf5fcda
2 changed files with 62 additions and 20 deletions

View File

@ -28,11 +28,17 @@ public:
#endif
bool Add(const void* object, uint32 flags = 0);
status_t Wait();
status_t Wait(const void* object, uint32 flags = 0);
status_t Wait(uint32 timeoutFlags = 0,
bigtime_t timeout = 0);
status_t Wait(const void* object, uint32 flags = 0,
bigtime_t timeout = 0);
inline ConditionVariable* Variable() const { return fVariable; }
private:
inline void AddToVariable(ConditionVariable* variable,
uint32 flags);
private:
ConditionVariable* fVariable;
struct thread* fThread;
@ -43,6 +49,10 @@ private:
class ConditionVariable : protected HashTableLink<ConditionVariable> {
public:
void Init(const void* object,
const char* objectType);
// for anonymous (unpublished) cvars
void Publish(const void* object,
const char* objectType);
void Unpublish(bool threadsLocked = false);
@ -50,6 +60,9 @@ public:
inline void NotifyOne(bool threadsLocked = false);
inline void NotifyAll(bool threadsLocked = false);
void Add(ConditionVariableEntry* entry,
uint32 flags = 0);
const void* Object() const { return fObject; }
static void ListAll();

View File

@ -96,18 +96,16 @@ ConditionVariableEntry::Add(const void* object, uint32 flags)
fThread = thread_get_current_thread();
InterruptsLocker _;
SpinLocker locker(sConditionVariablesLock);
InterruptsSpinLocker _(sConditionVariablesLock);
fVariable = sConditionVariableHash.Lookup(object);
struct thread* thread = thread_get_current_thread();
thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_CONDITION_VARIABLE,
fVariable);
thread_prepare_to_block(fThread, flags,
THREAD_BLOCK_TYPE_CONDITION_VARIABLE, fVariable);
if (fVariable == NULL) {
SpinLocker threadLocker(thread_spinlock);
thread_unblock_locked(thread, B_ENTRY_NOT_FOUND);
thread_unblock_locked(fThread, B_ENTRY_NOT_FOUND);
return false;
}
@ -119,7 +117,7 @@ ConditionVariableEntry::Add(const void* object, uint32 flags)
status_t
ConditionVariableEntry::Wait()
ConditionVariableEntry::Wait(uint32 timeoutFlags, bigtime_t timeout)
{
if (!are_interrupts_enabled()) {
panic("wait_for_condition_variable_entry() called with interrupts "
@ -130,7 +128,11 @@ ConditionVariableEntry::Wait()
InterruptsLocker _;
SpinLocker threadLocker(thread_spinlock);
status_t error = thread_block_locked(thread_get_current_thread());
status_t error;
if ((timeoutFlags & (B_RELATIVE_TIMEOUT | B_ABSOLUTE_TIMEOUT)) != 0)
error = thread_block_with_timeout_locked(timeoutFlags, timeout);
else
error = thread_block_locked(thread_get_current_thread());
threadLocker.Unlock();
SpinLocker locker(sConditionVariablesLock);
@ -146,17 +148,45 @@ ConditionVariableEntry::Wait()
status_t
ConditionVariableEntry::Wait(const void* object, uint32 flags)
ConditionVariableEntry::Wait(const void* object, uint32 flags,
bigtime_t timeout)
{
if (Add(object, flags))
return Wait();
return Wait(flags, timeout);
return B_ENTRY_NOT_FOUND;
}
inline void
ConditionVariableEntry::AddToVariable(ConditionVariable* variable, uint32 flags)
{
fThread = thread_get_current_thread();
thread_prepare_to_block(fThread, flags,
THREAD_BLOCK_TYPE_CONDITION_VARIABLE, fVariable);
// add to the variable
InterruptsSpinLocker _(sConditionVariablesLock);
fVariable = variable;
fVariable->fEntries.Add(this);
}
// #pragma mark - ConditionVariable
/*! Initialization method for anonymous (unpublished) condition variables.
*/
void
ConditionVariable::Init(const void* object, const char* objectType)
{
fObject = object;
fObjectType = objectType;
new(&fEntries) EntryList;
}
void
ConditionVariable::Publish(const void* object, const char* objectType)
{
@ -202,6 +232,13 @@ ConditionVariable::Unpublish(bool threadsLocked)
}
void
ConditionVariable::Add(ConditionVariableEntry* entry, uint32 flags)
{
entry->AddToVariable(this, flags);
}
/*static*/ void
ConditionVariable::ListAll()
{
@ -242,14 +279,6 @@ ConditionVariable::_Notify(bool all, bool threadsLocked)
SpinLocker threadLocker(threadsLocked ? NULL : &thread_spinlock);
SpinLocker locker(sConditionVariablesLock);
#if KDEBUG
ConditionVariable* variable = sConditionVariableHash.Lookup(fObject);
if (variable != this) {
panic("Condition variable %p not published, found: %p", this, variable);
return;
}
#endif
if (!fEntries.IsEmpty())
_NotifyChecked(all, B_OK);
}