* 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:
@@ -28,11 +28,17 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Add(const void* object, uint32 flags = 0);
|
bool Add(const void* object, uint32 flags = 0);
|
||||||
status_t Wait();
|
status_t Wait(uint32 timeoutFlags = 0,
|
||||||
status_t Wait(const void* object, uint32 flags = 0);
|
bigtime_t timeout = 0);
|
||||||
|
status_t Wait(const void* object, uint32 flags = 0,
|
||||||
|
bigtime_t timeout = 0);
|
||||||
|
|
||||||
inline ConditionVariable* Variable() const { return fVariable; }
|
inline ConditionVariable* Variable() const { return fVariable; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
inline void AddToVariable(ConditionVariable* variable,
|
||||||
|
uint32 flags);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ConditionVariable* fVariable;
|
ConditionVariable* fVariable;
|
||||||
struct thread* fThread;
|
struct thread* fThread;
|
||||||
@@ -43,6 +49,10 @@ private:
|
|||||||
|
|
||||||
class ConditionVariable : protected HashTableLink<ConditionVariable> {
|
class ConditionVariable : protected HashTableLink<ConditionVariable> {
|
||||||
public:
|
public:
|
||||||
|
void Init(const void* object,
|
||||||
|
const char* objectType);
|
||||||
|
// for anonymous (unpublished) cvars
|
||||||
|
|
||||||
void Publish(const void* object,
|
void Publish(const void* object,
|
||||||
const char* objectType);
|
const char* objectType);
|
||||||
void Unpublish(bool threadsLocked = false);
|
void Unpublish(bool threadsLocked = false);
|
||||||
@@ -50,6 +60,9 @@ public:
|
|||||||
inline void NotifyOne(bool threadsLocked = false);
|
inline void NotifyOne(bool threadsLocked = false);
|
||||||
inline void NotifyAll(bool threadsLocked = false);
|
inline void NotifyAll(bool threadsLocked = false);
|
||||||
|
|
||||||
|
void Add(ConditionVariableEntry* entry,
|
||||||
|
uint32 flags = 0);
|
||||||
|
|
||||||
const void* Object() const { return fObject; }
|
const void* Object() const { return fObject; }
|
||||||
|
|
||||||
static void ListAll();
|
static void ListAll();
|
||||||
|
|||||||
@@ -96,18 +96,16 @@ ConditionVariableEntry::Add(const void* object, uint32 flags)
|
|||||||
|
|
||||||
fThread = thread_get_current_thread();
|
fThread = thread_get_current_thread();
|
||||||
|
|
||||||
InterruptsLocker _;
|
InterruptsSpinLocker _(sConditionVariablesLock);
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
|
||||||
|
|
||||||
fVariable = sConditionVariableHash.Lookup(object);
|
fVariable = sConditionVariableHash.Lookup(object);
|
||||||
|
|
||||||
struct thread* thread = thread_get_current_thread();
|
thread_prepare_to_block(fThread, flags,
|
||||||
thread_prepare_to_block(thread, flags, THREAD_BLOCK_TYPE_CONDITION_VARIABLE,
|
THREAD_BLOCK_TYPE_CONDITION_VARIABLE, fVariable);
|
||||||
fVariable);
|
|
||||||
|
|
||||||
if (fVariable == NULL) {
|
if (fVariable == NULL) {
|
||||||
SpinLocker threadLocker(thread_spinlock);
|
SpinLocker threadLocker(thread_spinlock);
|
||||||
thread_unblock_locked(thread, B_ENTRY_NOT_FOUND);
|
thread_unblock_locked(fThread, B_ENTRY_NOT_FOUND);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +117,7 @@ ConditionVariableEntry::Add(const void* object, uint32 flags)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ConditionVariableEntry::Wait()
|
ConditionVariableEntry::Wait(uint32 timeoutFlags, bigtime_t timeout)
|
||||||
{
|
{
|
||||||
if (!are_interrupts_enabled()) {
|
if (!are_interrupts_enabled()) {
|
||||||
panic("wait_for_condition_variable_entry() called with interrupts "
|
panic("wait_for_condition_variable_entry() called with interrupts "
|
||||||
@@ -130,7 +128,11 @@ ConditionVariableEntry::Wait()
|
|||||||
InterruptsLocker _;
|
InterruptsLocker _;
|
||||||
|
|
||||||
SpinLocker threadLocker(thread_spinlock);
|
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();
|
threadLocker.Unlock();
|
||||||
|
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
SpinLocker locker(sConditionVariablesLock);
|
||||||
@@ -146,17 +148,45 @@ ConditionVariableEntry::Wait()
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ConditionVariableEntry::Wait(const void* object, uint32 flags)
|
ConditionVariableEntry::Wait(const void* object, uint32 flags,
|
||||||
|
bigtime_t timeout)
|
||||||
{
|
{
|
||||||
if (Add(object, flags))
|
if (Add(object, flags))
|
||||||
return Wait();
|
return Wait(flags, timeout);
|
||||||
return B_ENTRY_NOT_FOUND;
|
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
|
// #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
|
void
|
||||||
ConditionVariable::Publish(const void* object, const char* objectType)
|
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
|
/*static*/ void
|
||||||
ConditionVariable::ListAll()
|
ConditionVariable::ListAll()
|
||||||
{
|
{
|
||||||
@@ -242,14 +279,6 @@ ConditionVariable::_Notify(bool all, bool threadsLocked)
|
|||||||
SpinLocker threadLocker(threadsLocked ? NULL : &thread_spinlock);
|
SpinLocker threadLocker(threadsLocked ? NULL : &thread_spinlock);
|
||||||
SpinLocker locker(sConditionVariablesLock);
|
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())
|
if (!fEntries.IsEmpty())
|
||||||
_NotifyChecked(all, B_OK);
|
_NotifyChecked(all, B_OK);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user