Resolved race condition in methode Go of dialog windows.

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10276 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2004-11-28 19:05:01 +00:00
parent f0307bad5c
commit 76145367cb
6 changed files with 156 additions and 84 deletions
@@ -0,0 +1,42 @@
/*
* DialogWindow.h
* Copyright 2004 Michael Pfeiffer. All Rights Reserved.
*/
#ifndef __DIALOG_WINDOW_H
#define __DIALOG_WINDOW_H
#include <OS.h>
#include <Window.h>
class DialogWindow : public BWindow {
public:
DialogWindow(BRect frame,
const char *title,
window_type type,
uint32 flags,
uint32 workspace = B_CURRENT_WORKSPACE);
DialogWindow(BRect frame,
const char *title,
window_look look,
window_feel feel,
uint32 flags,
uint32 workspace = B_CURRENT_WORKSPACE);
status_t Go();
void SetResult(status_t result);
void MessageReceived(BMessage* msg);
enum {
kGetThreadId = 'dwti' // request thread id from window
};
private:
status_t fPreviousResult; // holds the result as long as fResult == NULL
volatile status_t *fResult;
};
#endif
+5 -9
View File
@@ -7,16 +7,16 @@
#define __JOBSETUPDLG_H
#include <View.h>
#include <Window.h>
#include "DialogWindow.h"
#include "JobData.h"
#include "Halftone.h"
#include "JSDSlider.h"
class BTextControl;
class BRadioButton;
class BCheckBox;
class BPopUpMenu;
class BSlider;
class JobData;
class PrinterData;
class PrinterCap;
@@ -45,8 +45,8 @@ private:
const PrinterCap *fPrinterCap;
BPopUpMenu *fColorType;
BPopUpMenu *fDitherType;
BSlider *fGamma;
BSlider *fInkDensity;
JSDSlider *fGamma;
JSDSlider *fInkDensity;
HalftoneView *fHalftone;
BRadioButton *fAll;
BCheckBox *fCollate;
@@ -56,17 +56,13 @@ private:
BPopUpMenu *fNup;
};
class JobSetupDlg : public BWindow {
class JobSetupDlg : public DialogWindow {
public:
JobSetupDlg(JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap);
~JobSetupDlg();
virtual bool QuitRequested();
virtual void MessageReceived(BMessage *message);
int Go();
private:
int fResult;
long fSemaphore;
BMessageFilter *fFilter;
};
@@ -7,7 +7,7 @@
#define __PAGESETUPDLG_H
#include <View.h>
#include <Window.h>
#include "DialogWindow.h"
class BRadioButton;
class BPopUpMenu;
@@ -31,17 +31,12 @@ private:
BPopUpMenu *fResolution;
};
class PageSetupDlg : public BWindow {
class PageSetupDlg : public DialogWindow {
public:
PageSetupDlg(JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap);
~PageSetupDlg();
virtual bool QuitRequested();
virtual void MessageReceived(BMessage *message);
int Go();
private:
int fResult;
long fSemaphore;
BMessageFilter *fFilter;
};
@@ -0,0 +1,88 @@
/*
* DialogWindow.h
* Copyright 2004 Michael Pfeiffer. All Rights Reserved.
*/
#include "DialogWindow.h"
#include <Messenger.h>
DialogWindow::DialogWindow(BRect frame,
const char *title,
window_type type,
uint32 flags,
uint32 workspace)
: BWindow(frame, title, type, flags, workspace)
, fPreviousResult(B_OK)
, fResult(NULL)
{
// nothing to do
}
DialogWindow::DialogWindow(BRect frame,
const char *title,
window_look look,
window_feel feel,
uint32 flags,
uint32 workspace)
: BWindow(frame, title, look, feel, flags, workspace)
, fPreviousResult(B_OK)
, fResult(NULL)
{
// nothing to do
}
void DialogWindow::MessageReceived(BMessage *msg)
{
if (msg->what == kGetThreadId) {
BMessage reply;
reply.AddInt32("thread_id", Thread());
msg->SendReply(&reply);
return;
}
BWindow::MessageReceived(msg);
}
status_t DialogWindow::Go()
{
BMessenger messenger(this, this);
// store result in local variable and
// initialize it with previous result
volatile status_t result = fPreviousResult;
// new results are stored on the stack
fResult = &result;
// show the window
Show();
// at this point we must not access member variables,
// because this object (the window) could already be deleted.
// get thread id of window thread
BMessage reply;
if (messenger.SendMessage(kGetThreadId, &reply) != B_OK) {
return B_ERROR;
}
thread_id windowThread;
if (reply.FindInt32("thread_id", &windowThread) != B_OK) {
return B_ERROR;
}
// wait for window thread to die
// The window thread will crash if the image holding the
// code used by the window thread is unloaded while the thread is
// still running!!!
status_t status = B_ERROR;
wait_for_thread(windowThread, &status);
return result;
}
void DialogWindow::SetResult(status_t result)
{
if (fResult != NULL) {
*fResult = result;
} else {
fPreviousResult = result;
}
}
@@ -35,6 +35,7 @@
#include "HalftoneView.h"
#include "JobSetupDlg.h"
#include "JobData.h"
#include "JSDSlider.h"
#include "PrinterData.h"
#include "PrinterCap.h"
#include "DbgMsg.h"
@@ -439,7 +440,8 @@ void JobSetupView::AttachedToWindow()
fHalftone->preview(fJobData->getGamma(), fJobData->getInkDensity(), fJobData->getDitherType(), fJobData->getColor() == JobData::kColor);
/* gamma */
fGamma = new BSlider(gamma_rect, "", "Gamma", new BMessage(kMsgQuality), -300, 300);
fGamma = new JSDSlider(gamma_rect, "gamma", "Gamma", new BMessage(kMsgQuality), -300, 300, B_BLOCK_THUMB);
fGamma->SetLimitLabels("Brighter", "Darker");
fGamma->SetValue(100 * log(fJobData->getGamma()) / log(2.0));
fGamma->SetHashMarks(B_HASH_MARKS_BOTH);
@@ -449,7 +451,8 @@ void JobSetupView::AttachedToWindow()
fGamma->SetTarget(this);
/* ink density */
fInkDensity = new BSlider(ink_density_rect, "", "Ink Density", new BMessage(kMsgQuality), 0, 127);
fInkDensity = new JSDSlider(ink_density_rect, "inkDensity", "Ink Density", new BMessage(kMsgQuality), 0, 127, B_BLOCK_THUMB);
fInkDensity->SetLimitLabels("Max", "Min");
fInkDensity->SetValue((int32)fJobData->getInkDensity());
fInkDensity->SetHashMarks(B_HASH_MARKS_TOP);
@@ -771,70 +774,44 @@ filter_result PrintKeyFilter(BMessage *msg, BHandler **target, BMessageFilter *f
//====================================================================
JobSetupDlg::JobSetupDlg(JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap)
: BWindow(BRect(100, 100, 100 + PRINT_WIDTH, 100 + PRINT_HEIGHT),
: DialogWindow(BRect(100, 100, 100 + PRINT_WIDTH, 100 + PRINT_HEIGHT),
"PrintJob Setup", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS)
{
fResult = 0;
/*
ostringstream oss;
oss << printer_data->get_printer_name() << " Print";
SetTitle(oss.str().c_str());
*/
Lock();
SetResult(B_ERROR);
JobSetupView *view = new JobSetupView(Bounds(), job_data, printer_data, printer_cap);
AddChild(view);
fFilter = new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, B_KEY_DOWN, &PrintKeyFilter);
AddCommonFilter(fFilter);
Unlock();
fSemaphore = create_sem(0, "JobSetupSem");
}
JobSetupDlg::~JobSetupDlg()
{
Lock();
RemoveCommonFilter(fFilter);
Unlock();
delete fFilter;
}
bool JobSetupDlg::QuitRequested()
{
fResult = B_ERROR;
release_sem(fSemaphore);
return true;
}
void JobSetupDlg::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case kMsgOK:
Lock();
((JobSetupView *)ChildAt(0))->UpdateJobData();
Unlock();
fResult = B_NO_ERROR;
release_sem(fSemaphore);
SetResult(B_NO_ERROR);
PostMessage(B_QUIT_REQUESTED);
break;
case kMsgCancel:
fResult = B_ERROR;
release_sem(fSemaphore);
PostMessage(B_QUIT_REQUESTED);
break;
default:
BWindow::MessageReceived(msg);
DialogWindow::MessageReceived(msg);
break;
}
}
int JobSetupDlg::Go()
{
Show();
acquire_sem(fSemaphore);
delete_sem(fSemaphore);
int value = fResult;
Lock();
Quit();
return value;
}
@@ -270,34 +270,20 @@ bool PageSetupView::UpdateJobData()
//====================================================================
PageSetupDlg::PageSetupDlg(JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap)
: BWindow(BRect(100, 100, 100 + PAGESETUP_WIDTH, 100 + PAGESETUP_HEIGHT),
: DialogWindow(BRect(100, 100, 100 + PAGESETUP_WIDTH, 100 + PAGESETUP_HEIGHT),
"Page Setup", B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL,
B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE)
{
fResult = 0;
/*
ostringstream oss;
oss << printer_data->get_printer_name() << " Setup";
SetTitle(title.str().c_str());
*/
Lock();
PageSetupView *view = new PageSetupView(Bounds(), job_data, printer_data, printer_cap);
AddChild(view);
Unlock();
fSemaphore = create_sem(0, "PageSetupSem");
}
PageSetupDlg::~PageSetupDlg()
{
}
bool PageSetupDlg::QuitRequested()
{
fResult = B_ERROR;
release_sem(fSemaphore);
return true;
SetResult(B_ERROR);
}
void PageSetupDlg::MessageReceived(BMessage *msg)
@@ -307,28 +293,16 @@ void PageSetupDlg::MessageReceived(BMessage *msg)
Lock();
((PageSetupView *)ChildAt(0))->UpdateJobData();
Unlock();
fResult = B_NO_ERROR;
release_sem(fSemaphore);
SetResult(B_NO_ERROR);
PostMessage(B_QUIT_REQUESTED);
break;
case kMsgCancel:
fResult = B_ERROR;
release_sem(fSemaphore);
PostMessage(B_QUIT_REQUESTED);
break;
default:
BWindow::MessageReceived(msg);
break;
DialogWindow::MessageReceived(msg);
}
}
int PageSetupDlg::Go()
{
Show();
acquire_sem(fSemaphore);
delete_sem(fSemaphore);
int value = fResult;
Lock();
Quit();
return value;
}