Fixed SetCommonFilterList() so that the same list can't be added to more

than one looper.
Implemented UnlockFully(), and changed destructor and Quit() to use it.
Reordered the destructor slightly so as to delete fLockSem *after* the call
to UnlockFully().


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@869 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
ejakowatz 2002-08-24 20:38:15 +00:00
parent 89c12458ee
commit cb5b0f6d58

View File

@ -174,7 +174,6 @@ BLooper::~BLooper()
// isn't done.
// kill_thread(fTaskID);
delete fQueue;
delete_sem(fLockSem);
delete_port(fMsgPort);
// Clean up our filters
@ -194,9 +193,9 @@ BLooper::~BLooper()
}
}
RemoveLooper(this);
UnlockFully();
RemoveLooper(this);
delete_sem(fLockSem);
}
//------------------------------------------------------------------------------
BLooper::BLooper(BMessage* data)
@ -559,9 +558,10 @@ DBG(OUT(" Run() has already been called and we are not the looper thread\n"));
// bonefish: We need to unlock here. Otherwise the looper thread can't
// dispatch the _QUIT_ message we're going to post.
do {
Unlock();
} while (IsLocked());
// do {
// Unlock();
// } while (IsLocked());
UnlockFully();
// As per the BeBook, if we've been called by a thread other than
// our own, the rest of the message queue has to get processed. So
@ -806,11 +806,13 @@ void BLooper::AddCommonFilter(BMessageFilter* filter)
if (!IsLocked())
{
debugger("Owning Looper must be locked before calling AddCommonFilter");
return;
}
if (filter->Looper())
{
debugger("A MessageFilter can only be used once.");
return;
}
if (!fCommonFilters)
@ -852,6 +854,10 @@ void BLooper::SetCommonFilterList(BList* filters)
// destroyed will have a problem when it tries to delete a filter list that
// has already been deleted. In R5, this results in a general protection
// fault; here it ends in a segment violation.
// TODO: Fix
// by checking first filter in list for ownership issues. Go to
// debugger with something like "A MessageFilter can only be used
// once." and return with out setting the list.
if (!IsLocked())
{
debugger("Owning Looper must be locked before calling "
@ -859,6 +865,21 @@ void BLooper::SetCommonFilterList(BList* filters)
return;
}
BMessageFilter* filter;
if (filters)
{
// Check for ownership issues
for (int32 i = 0; i < filters->CountItems(); ++i)
{
filter = (BMessageFilter*)filters->ItemAt(i);
if (filter->Looper())
{
debugger("A MessageFilter can only be used once.");
return;
}
}
}
if (fCommonFilters)
{
for (int32 i = 0; i < fCommonFilters->CountItems(); ++i)
@ -876,7 +897,8 @@ void BLooper::SetCommonFilterList(BList* filters)
{
for (int32 i = 0; i < fCommonFilters->CountItems(); ++i)
{
((BMessageFilter*)fCommonFilters->ItemAt(i))->SetLooper(this);
filter = (BMessageFilter*)fCommonFilters->ItemAt(i);
filter->SetLooper(this);
}
}
}
@ -889,7 +911,7 @@ BList* BLooper::CommonFilterList() const
status_t BLooper::Perform(perform_code d, void* arg)
{
// This is sort of what we're doing for this function everywhere
return B_ERROR;
return BHandler::Perform(d, arg);
}
//------------------------------------------------------------------------------
BMessage* BLooper::MessageFromPort(bigtime_t timeout)
@ -1044,6 +1066,7 @@ DBG(OUT("BLooper::_Lock() done 4\n"));
}
}
// Is the looper trying to lock itself?
// Check for nested lock attempt
curThread = find_thread(NULL);
if (curThread == loop->fOwner)
@ -1054,6 +1077,7 @@ DBG(OUT("BLooper::_Lock() done 5: fOwnerCount: %ld\n", loop->fOwnerCount));
return B_OK;
}
// Something external to the looper is attempting to lock
// Cache the semaphore
sem = loop->fLockSem;
@ -1555,7 +1579,26 @@ BHandler* BLooper::resolve_specifier(BHandler* target, BMessage* msg)
//------------------------------------------------------------------------------
void BLooper::UnlockFully()
{
// TODO: implement
AssertLocked();
/**
@note What we're doing here is completely undoing the current owner's lock
on the looper. This is actually pretty easy, since the owner only
has a single aquisition on the semaphore; every subsequent "lock"
is just an increment to the owner count. The whole thing is quite
similar to Unlock(), except that we clear the ownership variables,
rather than merely decrementing them.
*/
// Clear the owner count
fOwnerCount = 0;
// Nobody owns the lock now
fOwner = -1;
// There is now one less thread holding a lock on this looper
long atomicCount = atomic_add(&fAtomicCount, -1);
if (atomicCount > 0)
{
release_sem(fLockSem);
}
}
//------------------------------------------------------------------------------
void BLooper::AddLooper(BLooper* loop)