haiku/src/apps/packageinstaller/BlockingWindow.cpp

93 lines
1.8 KiB
C++

/*
* Copyright (c) 2007-2014, Haiku, Inc.
* Distributed under the terms of the MIT license.
*
* Author:
* Łukasz 'Sil2100' Zemczak <sil2100@vexillium.org>
* Stephan Aßmus <superstippi@gmx.de>
*/
#include "PackageImageViewer.h"
BlockingWindow::BlockingWindow(BRect frame, const char* title, uint32 flags)
:
BWindow(frame, title, B_MODAL_WINDOW,
B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_NOT_CLOSABLE | flags),
fSemaphore(-1),
fReturnValue(0)
{
}
BlockingWindow::~BlockingWindow()
{
}
bool
BlockingWindow::QuitRequested()
{
ReleaseSem(0);
return true;
}
int32
BlockingWindow::Go()
{
int32 returnValue = 0;
// Since this class can be thought of as a modified BAlert window, no use
// to reinvent a well fledged wheel. This concept has been borrowed from
// the current BAlert implementation
fSemaphore = create_sem(0, "PackageInstaller BlockingWindow");
if (fSemaphore < B_OK) {
Quit();
return returnValue;
}
thread_id callingThread = find_thread(NULL);
BWindow* window = dynamic_cast<BWindow*>(BLooper::LooperForThread(
callingThread));
Show();
if (window != NULL) {
// Make sure calling window thread, which is blocked here, is updating
// the window from time to time.
status_t ret;
for (;;) {
do {
ret = acquire_sem_etc(fSemaphore, 1, B_RELATIVE_TIMEOUT, 50000);
} while (ret == B_INTERRUPTED);
if (ret == B_BAD_SEM_ID)
break;
window->UpdateIfNeeded();
}
} else {
// Since there are no spinlocks, wait until the semaphore is free
while (acquire_sem(fSemaphore) == B_INTERRUPTED) {
}
}
returnValue = fReturnValue;
if (Lock())
Quit();
return returnValue;
}
void
BlockingWindow::ReleaseSem(int32 returnValue)
{
if (fSemaphore >= B_OK) {
delete_sem(fSemaphore);
fSemaphore = -1;
fReturnValue = returnValue;
}
}