Implemented BLooper::check_lock().

Use AssertLock() more often instead of varying debugger messages.
Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13167 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2005-06-16 02:56:03 +00:00
parent 1ae95ac872
commit 410d5c37d5

View File

@ -309,13 +309,17 @@ BLooper::MessageReceived(BMessage *msg)
// saying it does nothing. Investigate. // saying it does nothing. Investigate.
BHandler::MessageReceived(msg); BHandler::MessageReceived(msg);
} }
//------------------------------------------------------------------------------
BMessage* BLooper::CurrentMessage() const
BMessage*
BLooper::CurrentMessage() const
{ {
return fLastMessage; return fLastMessage;
} }
//------------------------------------------------------------------------------
BMessage* BLooper::DetachCurrentMessage()
BMessage*
BLooper::DetachCurrentMessage()
{ {
Lock(); Lock();
BMessage* msg = fLastMessage; BMessage* msg = fLastMessage;
@ -324,24 +328,22 @@ BMessage* BLooper::DetachCurrentMessage()
Unlock(); Unlock();
return msg; return msg;
} }
//------------------------------------------------------------------------------
BMessageQueue* BLooper::MessageQueue() const
BMessageQueue*
BLooper::MessageQueue() const
{ {
return fQueue; return fQueue;
} }
//------------------------------------------------------------------------------
bool BLooper::IsMessageWaiting() const
bool
BLooper::IsMessageWaiting() const
{ {
if (!IsLocked()) AssertLocked();
{
debugger("The Looper must be locked before calling IsMsgWaiting");
return false;
}
if (!fQueue->IsEmpty()) if (!fQueue->IsEmpty())
{
return true; return true;
}
/** /**
@note: What we're doing here differs slightly from the R5 implementation. @note: What we're doing here differs slightly from the R5 implementation.
@ -355,65 +357,49 @@ bool BLooper::IsMessageWaiting() const
where I come from. ;) where I come from. ;)
*/ */
int32 count; int32 count;
do do {
{
count = port_buffer_size_etc(fMsgPort, B_RELATIVE_TIMEOUT, 0); count = port_buffer_size_etc(fMsgPort, B_RELATIVE_TIMEOUT, 0);
} while (count == B_INTERRUPTED); } while (count == B_INTERRUPTED);
return count > 0; return count > 0;
} }
//------------------------------------------------------------------------------
void BLooper::AddHandler(BHandler* handler)
void
BLooper::AddHandler(BHandler* handler)
{ {
if (!handler) if (handler == NULL)
{
return; return;
}
if (!IsLocked()) AssertLocked();
{
debugger("Looper must be locked before calling AddHandler.");
}
if (handler->Looper() == NULL) if (handler->Looper() == NULL) {
{
fHandlers.AddItem(handler); fHandlers.AddItem(handler);
handler->SetLooper(this); handler->SetLooper(this);
if (handler != this) // avoid a cycle if (handler != this) // avoid a cycle
handler->SetNextHandler(this); handler->SetNextHandler(this);
BList* Filters = handler->FilterList();
if (Filters) BList* filters = handler->FilterList();
{ if (filters) {
for (int32 i = 0; i < Filters->CountItems(); ++i) for (int32 i = 0; i < filters->CountItems(); ++i) {
{ ((BMessageFilter*)filters->ItemAt(i))->SetLooper(this);
((BMessageFilter*)Filters->ItemAt(i))->SetLooper(this);
} }
} }
} }
} }
//------------------------------------------------------------------------------
bool BLooper::RemoveHandler(BHandler* handler)
bool
BLooper::RemoveHandler(BHandler* handler)
{ {
// R5 implementation didn't bother to check its params, thus NULL handlers if (handler == NULL)
// will seg fault. Bad form, you know.
if (!handler)
{
return false; return false;
}
// Correction; testing shows the looper *does* need to be locked for this; AssertLocked();
// it just doesn't use AssertLocked() for that.
if (!IsLocked())
{
debugger("Looper must be locked before calling RemoveHandler.");
}
if (handler->Looper() == this && fHandlers.RemoveItem(handler)) if (handler->Looper() == this && fHandlers.RemoveItem(handler)) {
{
if (handler == fPreferred) if (handler == fPreferred)
{
fPreferred = NULL; fPreferred = NULL;
}
handler->SetNextHandler(NULL); handler->SetNextHandler(NULL);
handler->SetLooper(NULL); handler->SetLooper(NULL);
@ -422,47 +408,48 @@ bool BLooper::RemoveHandler(BHandler* handler)
return false; return false;
} }
//------------------------------------------------------------------------------
int32 BLooper::CountHandlers() const
int32
BLooper::CountHandlers() const
{ {
AssertLocked(); AssertLocked();
return fHandlers.CountItems(); return fHandlers.CountItems();
} }
//------------------------------------------------------------------------------
BHandler* BLooper::HandlerAt(int32 index) const
BHandler*
BLooper::HandlerAt(int32 index) const
{ {
if (!IsLocked()) AssertLocked();
{
debugger("Looper must be locked before calling HandlerAt.");
}
return (BHandler*)fHandlers.ItemAt(index); return (BHandler*)fHandlers.ItemAt(index);
} }
//------------------------------------------------------------------------------
int32 BLooper::IndexOf(BHandler* handler) const
int32
BLooper::IndexOf(BHandler* handler) const
{ {
if (!IsLocked()) AssertLocked();
{
debugger("Looper must be locked before calling IndexOf.");
}
return fHandlers.IndexOf(handler); return fHandlers.IndexOf(handler);
} }
//------------------------------------------------------------------------------
BHandler* BLooper::PreferredHandler() const
BHandler*
BLooper::PreferredHandler() const
{ {
return fPreferred; return fPreferred;
} }
//------------------------------------------------------------------------------
void BLooper::SetPreferredHandler(BHandler* handler)
void
BLooper::SetPreferredHandler(BHandler* handler)
{ {
if (handler && handler->Looper() == this && IndexOf(handler) >= 0) if (handler && handler->Looper() == this && IndexOf(handler) >= 0) {
{
fPreferred = handler; fPreferred = handler;
} } else {
else
{
fPreferred = NULL; fPreferred = NULL;
} }
} }
@ -514,8 +501,7 @@ BLooper::Quit()
PRINT((" is locked\n")); PRINT((" is locked\n"));
if (!fRunCalled) if (!fRunCalled) {
{
PRINT((" Run() has not been called yet\n")); PRINT((" Run() has not been called yet\n"));
fTerminating = true; fTerminating = true;
delete this; delete this;
@ -574,8 +560,10 @@ BLooper::Lock()
// Defer to global _Lock(); see notes there // Defer to global _Lock(); see notes there
return _Lock(this, -1, B_INFINITE_TIMEOUT) == B_OK; return _Lock(this, -1, B_INFINITE_TIMEOUT) == B_OK;
} }
//------------------------------------------------------------------------------
void BLooper::Unlock()
void
BLooper::Unlock()
{ {
PRINT(("BLooper::Unlock()\n")); PRINT(("BLooper::Unlock()\n"));
// Make sure we're locked to begin with // Make sure we're locked to begin with
@ -585,8 +573,7 @@ PRINT(("BLooper::Unlock()\n"));
--fOwnerCount; --fOwnerCount;
PRINT((" fOwnerCount now: %ld\n", fOwnerCount)); PRINT((" fOwnerCount now: %ld\n", fOwnerCount));
// Check to see if the owner still wants a lock // Check to see if the owner still wants a lock
if (fOwnerCount == 0) if (fOwnerCount == 0) {
{
// Set fOwner to invalid thread_id (< 0) // Set fOwner to invalid thread_id (< 0)
fOwner = -1; fOwner = -1;
@ -604,21 +591,21 @@ PRINT((" fAtomicCount now: %ld\n", fAtomicCount));
} }
PRINT(("BLooper::Unlock() done\n")); PRINT(("BLooper::Unlock() done\n"));
} }
//------------------------------------------------------------------------------
bool BLooper::IsLocked() const
bool
BLooper::IsLocked() const
{ {
// We have to lock the list for the call to IsLooperValid(). Has the side // We have to lock the list for the call to IsLooperValid(). Has the side
// effect of not letting the looper get deleted while we're here. // effect of not letting the looper get deleted while we're here.
BObjectLocker<BLooperList> ListLock(gLooperList); BObjectLocker<BLooperList> ListLock(gLooperList);
if (!ListLock.IsLocked()) if (!ListLock.IsLocked()) {
{
// If we can't lock the list, our semaphore is probably toast // If we can't lock the list, our semaphore is probably toast
return false; return false;
} }
if (!IsLooperValid(this)) if (!IsLooperValid(this)) {
{
// The looper is gone, so of course it's not locked // The looper is gone, so of course it's not locked
return false; return false;
} }
@ -626,56 +613,71 @@ bool BLooper::IsLocked() const
// Got this from Jeremy's BLocker implementation // Got this from Jeremy's BLocker implementation
return find_thread(NULL) == fOwner; return find_thread(NULL) == fOwner;
} }
//------------------------------------------------------------------------------
status_t BLooper::LockWithTimeout(bigtime_t timeout)
status_t
BLooper::LockWithTimeout(bigtime_t timeout)
{ {
return _Lock(this, -1, timeout); return _Lock(this, -1, timeout);
} }
//------------------------------------------------------------------------------
thread_id BLooper::Thread() const
thread_id
BLooper::Thread() const
{ {
return fTaskID; return fTaskID;
} }
//------------------------------------------------------------------------------
team_id BLooper::Team() const
team_id
BLooper::Team() const
{ {
return sTeamID; return sTeamID;
} }
//------------------------------------------------------------------------------
BLooper* BLooper::LooperForThread(thread_id tid)
BLooper*
BLooper::LooperForThread(thread_id tid)
{ {
BObjectLocker<BLooperList> ListLock(gLooperList); BObjectLocker<BLooperList> ListLock(gLooperList);
if (ListLock.IsLocked()) if (ListLock.IsLocked())
{
return gLooperList.LooperForThread(tid); return gLooperList.LooperForThread(tid);
}
return NULL; return NULL;
} }
//------------------------------------------------------------------------------
thread_id BLooper::LockingThread() const
thread_id
BLooper::LockingThread() const
{ {
return fOwner; return fOwner;
} }
//------------------------------------------------------------------------------
int32 BLooper::CountLocks() const
int32
BLooper::CountLocks() const
{ {
return fOwnerCount; return fOwnerCount;
} }
//------------------------------------------------------------------------------
int32 BLooper::CountLockRequests() const
int32
BLooper::CountLockRequests() const
{ {
return fAtomicCount; return fAtomicCount;
} }
//------------------------------------------------------------------------------
sem_id BLooper::Sem() const
sem_id
BLooper::Sem() const
{ {
return fLockSem; return fLockSem;
} }
//------------------------------------------------------------------------------
BHandler* BLooper::ResolveSpecifier(BMessage* msg, int32 index,
BMessage* specifier, int32 form, BHandler*
const char* property) BLooper::ResolveSpecifier(BMessage* msg, int32 index,
BMessage* specifier, int32 form, const char* property)
{ {
/** /**
@note When I was first dumping the results of GetSupportedSuites() from @note When I was first dumping the results of GetSupportedSuites() from
@ -693,29 +695,23 @@ BHandler* BLooper::ResolveSpecifier(BMessage* msg, int32 index,
uint32 data; uint32 data;
status_t err = B_OK; status_t err = B_OK;
const char* errMsg = ""; const char* errMsg = "";
if (PropertyInfo.FindMatch(msg, index, specifier, form, property, &data) >= 0) if (PropertyInfo.FindMatch(msg, index, specifier, form, property, &data) >= 0) {
{ switch (data) {
switch (data)
{
case BLOOPER_PROCESS_INTERNALLY: case BLOOPER_PROCESS_INTERNALLY:
return this; return this;
case BLOOPER_HANDLER_BY_INDEX: case BLOOPER_HANDLER_BY_INDEX:
{ {
int32 index = specifier->FindInt32("index"); int32 index = specifier->FindInt32("index");
if (form == B_REVERSE_INDEX_SPECIFIER) if (form == B_REVERSE_INDEX_SPECIFIER) {
{
index = CountHandlers() - index; index = CountHandlers() - index;
} }
BHandler* target = HandlerAt(index); BHandler* target = HandlerAt(index);
if (target) if (target) {
{
// Specifier has been fully handled // Specifier has been fully handled
msg->PopSpecifier(); msg->PopSpecifier();
return target; return target;
} } else {
else
{
err = B_BAD_INDEX; err = B_BAD_INDEX;
errMsg = "handler index out of range"; errMsg = "handler index out of range";
} }
@ -727,11 +723,9 @@ BHandler* BLooper::ResolveSpecifier(BMessage* msg, int32 index,
errMsg = "Didn't understand the specifier(s)"; errMsg = "Didn't understand the specifier(s)";
break; break;
} }
} } else {
else
{
return BHandler::ResolveSpecifier(msg, index, specifier, form, return BHandler::ResolveSpecifier(msg, index, specifier, form,
property); property);
} }
BMessage Reply(B_MESSAGE_NOT_UNDERSTOOD); BMessage Reply(B_MESSAGE_NOT_UNDERSTOOD);
@ -741,84 +735,65 @@ BHandler* BLooper::ResolveSpecifier(BMessage* msg, int32 index,
return NULL; return NULL;
} }
//------------------------------------------------------------------------------
status_t BLooper::GetSupportedSuites(BMessage* data)
status_t
BLooper::GetSupportedSuites(BMessage* data)
{ {
status_t err = B_OK; if (data == NULL)
return B_BAD_VALUE;
if (!data)
{ status_t status = data->AddString("Suites", "suite/vnd.Be-handler");
err = B_BAD_VALUE; if (status == B_OK) {
BPropertyInfo PropertyInfo(gLooperPropInfo);
status = data->AddFlat("message", &PropertyInfo);
if (status == B_OK)
status = BHandler::GetSupportedSuites(data);
} }
if (!err) return status;
{
err = data->AddString("Suites", "suite/vnd.Be-handler");
if (!err)
{
BPropertyInfo PropertyInfo(gLooperPropInfo);
err = data->AddFlat("message", &PropertyInfo);
if (!err)
{
err = BHandler::GetSupportedSuites(data);
}
}
}
return err;
} }
//------------------------------------------------------------------------------
void BLooper::AddCommonFilter(BMessageFilter* filter)
void
BLooper::AddCommonFilter(BMessageFilter* filter)
{ {
if (!filter) if (!filter)
{
return; return;
}
if (!IsLocked()) AssertLocked();
{
debugger("Owning Looper must be locked before calling AddCommonFilter");
return;
}
if (filter->Looper()) if (filter->Looper()) {
{
debugger("A MessageFilter can only be used once."); debugger("A MessageFilter can only be used once.");
return; return;
} }
if (!fCommonFilters) if (!fCommonFilters)
{
fCommonFilters = new BList(FILTER_LIST_BLOCK_SIZE); fCommonFilters = new BList(FILTER_LIST_BLOCK_SIZE);
}
filter->SetLooper(this); filter->SetLooper(this);
fCommonFilters->AddItem(filter); fCommonFilters->AddItem(filter);
} }
//------------------------------------------------------------------------------
bool BLooper::RemoveCommonFilter(BMessageFilter* filter)
bool
BLooper::RemoveCommonFilter(BMessageFilter* filter)
{ {
if (!IsLocked()) AssertLocked();
{
debugger("Owning Looper must be locked before calling "
"RemoveCommonFilter");
return false;
}
if (!fCommonFilters) if (!fCommonFilters)
{
return false; return false;
}
bool result = fCommonFilters->RemoveItem(filter); bool result = fCommonFilters->RemoveItem(filter);
if (result) if (result)
{
filter->SetLooper(NULL); filter->SetLooper(NULL);
}
return result; return result;
} }
//------------------------------------------------------------------------------
void BLooper::SetCommonFilterList(BList* filters)
void
BLooper::SetCommonFilterList(BList* filters)
{ {
// We have a somewhat serious problem here. It is entirely possible in R5 // We have a somewhat serious problem here. It is entirely possible in R5
// to assign a given list of filters to *two* BLoopers simultaneously. This // to assign a given list of filters to *two* BLoopers simultaneously. This
@ -827,32 +802,22 @@ void BLooper::SetCommonFilterList(BList* filters)
// has already been deleted. In R5, this results in a general protection // has already been deleted. In R5, this results in a general protection
// fault. We fix this by checking the filter list for ownership issues. // fault. We fix this by checking the filter list for ownership issues.
if (!IsLocked()) AssertLocked();
{
debugger("Owning Looper must be locked before calling "
"SetCommonFilterList");
return;
}
BMessageFilter* filter; BMessageFilter* filter;
if (filters) if (filters) {
{
// Check for ownership issues // Check for ownership issues
for (int32 i = 0; i < filters->CountItems(); ++i) for (int32 i = 0; i < filters->CountItems(); ++i) {
{
filter = (BMessageFilter*)filters->ItemAt(i); filter = (BMessageFilter*)filters->ItemAt(i);
if (filter->Looper()) if (filter->Looper()) {
{
debugger("A MessageFilter can only be used once."); debugger("A MessageFilter can only be used once.");
return; return;
} }
} }
} }
if (fCommonFilters) if (fCommonFilters) {
{ for (int32 i = 0; i < fCommonFilters->CountItems(); ++i) {
for (int32 i = 0; i < fCommonFilters->CountItems(); ++i)
{
delete (BMessageFilter*)fCommonFilters->ItemAt(i); delete (BMessageFilter*)fCommonFilters->ItemAt(i);
} }
@ -862,67 +827,58 @@ void BLooper::SetCommonFilterList(BList* filters)
// Per the BeBook, we take ownership of the list // Per the BeBook, we take ownership of the list
fCommonFilters = filters; fCommonFilters = filters;
if (fCommonFilters) if (fCommonFilters) {
{ for (int32 i = 0; i < fCommonFilters->CountItems(); ++i) {
for (int32 i = 0; i < fCommonFilters->CountItems(); ++i)
{
filter = (BMessageFilter*)fCommonFilters->ItemAt(i); filter = (BMessageFilter*)fCommonFilters->ItemAt(i);
filter->SetLooper(this); filter->SetLooper(this);
} }
} }
} }
//------------------------------------------------------------------------------
BList* BLooper::CommonFilterList() const
BList*
BLooper::CommonFilterList() const
{ {
return fCommonFilters; return fCommonFilters;
} }
//------------------------------------------------------------------------------
status_t BLooper::Perform(perform_code d, void* arg)
status_t
BLooper::Perform(perform_code d, void* arg)
{ {
// This is sort of what we're doing for this function everywhere // This is sort of what we're doing for this function everywhere
return BHandler::Perform(d, arg); return BHandler::Perform(d, arg);
} }
//------------------------------------------------------------------------------
BMessage* BLooper::MessageFromPort(bigtime_t timeout)
BMessage*
BLooper::MessageFromPort(bigtime_t timeout)
{ {
return ReadMessageFromPort(timeout); return ReadMessageFromPort(timeout);
} }
//------------------------------------------------------------------------------
void BLooper::_ReservedLooper1()
{ void BLooper::_ReservedLooper1() {}
} void BLooper::_ReservedLooper2() {}
//------------------------------------------------------------------------------ void BLooper::_ReservedLooper3() {}
void BLooper::_ReservedLooper2() void BLooper::_ReservedLooper4() {}
{ void BLooper::_ReservedLooper5() {}
} void BLooper::_ReservedLooper6() {}
//------------------------------------------------------------------------------
void BLooper::_ReservedLooper3()
{
}
//------------------------------------------------------------------------------
void BLooper::_ReservedLooper4()
{
}
//------------------------------------------------------------------------------
void BLooper::_ReservedLooper5()
{
}
//------------------------------------------------------------------------------
void BLooper::_ReservedLooper6()
{
}
//------------------------------------------------------------------------------
BLooper::BLooper(const BLooper&) BLooper::BLooper(const BLooper&)
{ {
// Copy construction not allowed // Copy construction not allowed
} }
//------------------------------------------------------------------------------
BLooper& BLooper::operator=(const BLooper& ) BLooper& BLooper::operator=(const BLooper& )
{ {
// Looper copying not allowed // Looper copying not allowed
return *this; return *this;
} }
//------------------------------------------------------------------------------
BLooper::BLooper(int32 priority, port_id port, const char* name) BLooper::BLooper(int32 priority, port_id port, const char* name)
{ {
// This must be a legacy constructor // This must be a legacy constructor
@ -1508,7 +1464,11 @@ BLooper::apply_filters(BList* list, BMessage* msg, BHandler* target)
void void
BLooper::check_lock() BLooper::check_lock()
{ {
// NOTE: any use for this? // This is a cheap variant of AssertLocked()
// It is used in situations where it's clear that the looper is valid,
// ie. from handlers
if (fOwner == -1 || fOwner != find_thread(NULL))
debugger("Looper must be locked.");
} }