Exemple #1
0
/*! \brief Begins executing the thread's ThreadFunction()
*/
status_t
RegistrarThread::Run()
{
	status_t err = InitCheck();
	if (err == B_OK) {
		fId = spawn_thread(&RegistrarThread::EntryFunction, fName,
			fPriority, (void*)this);
		err = fId >= 0 ? B_OK : fId;
		if (err == B_OK)	
			err = resume_thread(fId);
	}
	return err;
}
MidiPortProducer::MidiPortProducer(int fd, const char *name)
	: BMidiLocalProducer(name),
	fFileDescriptor(fd), fKeepRunning(true)
	
{
	BString tmp = name;
	tmp << " reader";
	
	fReaderThread = spawn_thread(
		_ReaderThread, tmp.String(), B_URGENT_PRIORITY, this);

	resume_thread(fReaderThread);
}
Exemple #3
0
void
BDirectWindow::_InitData()
{
	fConnectionEnable = false;
	fIsFullScreen = false;
	fInDirectConnect = false;

	fInitStatus = 0;

	status_t status = B_ERROR;
	struct direct_window_sync_data syncData;

	fLink->StartMessage(AS_DIRECT_WINDOW_GET_SYNC_DATA);
	if (fLink->FlushWithReply(status) == B_OK && status == B_OK)
		fLink->Read<direct_window_sync_data>(&syncData);

	if (status != B_OK)
		return;

#if DW_NEEDS_LOCKING
	fDirectLock = 0;
	fDirectLockCount = 0;
	fDirectLockOwner = -1;
	fDirectLockStack = NULL;
	fDirectSem = create_sem(0, "direct sem");
	if (fDirectSem > 0)
		fInitStatus |= DW_STATUS_SEM_CREATED;
#endif

	fSourceClippingArea = syncData.area;
	fDisableSem = syncData.disable_sem;
	fDisableSemAck = syncData.disable_sem_ack;

	fClonedClippingArea = clone_area("cloned direct area", (void**)&fBufferDesc,
		B_ANY_ADDRESS, B_READ_AREA, fSourceClippingArea);

	if (fClonedClippingArea > 0) {
		fInitStatus |= DW_STATUS_AREA_CLONED;

		fDirectDaemonId = spawn_thread(_daemon_thread, "direct daemon",
			B_DISPLAY_PRIORITY, this);

		if (fDirectDaemonId > 0) {
			fDaemonKiller = false;
			if (resume_thread(fDirectDaemonId) == B_OK)
				fInitStatus |= DW_STATUS_THREAD_STARTED;
			else
				kill_thread(fDirectDaemonId);
		}
	}
}
Exemple #4
0
status_t
ethernet_up(net_device *_device)
{
	ethernet_device *device = (ethernet_device *)_device;

	device->fd = open(device->name, O_RDWR);
	if (device->fd < 0)
		return errno;

	uint64 dummy;
	if (ioctl(device->fd, ETHER_INIT, &dummy, sizeof(dummy)) < 0)
		goto err;

	if (ioctl(device->fd, ETHER_GETADDR, device->address.data, ETHER_ADDRESS_LENGTH) < 0)
		goto err;

	if (ioctl(device->fd, ETHER_GETFRAMESIZE, &device->frame_size, sizeof(uint32)) < 0) {
		// this call is obviously optional
		device->frame_size = ETHER_MAX_FRAME_SIZE;
	}

	if (update_link_state(device, false) == B_OK) {
		// device supports retrieval of the link state

		// Set the change notification semaphore; doesn't matter
		// if this is supported by the device or not
		ioctl(device->fd, ETHER_SET_LINK_STATE_SEM, &sLinkChangeSemaphore,
			sizeof(sem_id));

		MutexLocker _(&sListLock);

		if (sCheckList.IsEmpty()) {
			// start thread
			sLinkCheckerThread = spawn_kernel_thread(ethernet_link_checker,
				"ethernet link state checker", B_LOW_PRIORITY, NULL);
			if (sLinkCheckerThread >= B_OK)
				resume_thread(sLinkCheckerThread);
		}

		sCheckList.Add(device);
	}

	device->address.length = ETHER_ADDRESS_LENGTH;
	device->mtu = device->frame_size - device->header_length;
	return B_OK;

err:
	close(device->fd);
	device->fd = -1;
	return errno;
}
Exemple #5
0
status_t
Worker::Init()
{
	fThread = spawn_thread(&Worker::_Process, "worker", B_NORMAL_PRIORITY,
		this);
	if (fThread < 0)
		return fThread;

	status_t status = resume_thread(fThread);
	if (status == B_OK)
		atomic_add(&sWorkerCount, 1);

	return status;
}
Exemple #6
0
int
main(int argc, char** argv)
{
	thread_id thread = spawn_thread(&abort_thread, "abort test",
		B_NORMAL_PRIORITY, NULL);
	resume_thread(thread);

	status_t status = wait_for_thread(thread, NULL);
	fprintf(stderr, "abort thread aborted: %s\n", strerror(status));

	snooze(1000000LL);
	fprintf(stderr, "main exiting\n");
	return 0;
}
// Async. processing of received message
void 
PrintServerApp::AsyncHandleMessage(BMessage* msg)
{
	AsyncThreadParams* data = new AsyncThreadParams(this, fDefaultPrinter, msg);

	thread_id tid = spawn_thread(async_thread, "async", B_NORMAL_PRIORITY,
		(void*)data);

	if (tid > 0) {
		resume_thread(tid);
	} else {
		delete data;
	}
}
Exemple #8
0
extern "C" Display* XOpenDisplay(const char *name) {
  Display* display = new _XDisplay;
  memset(display, 0, sizeof(Display));
  main_thread = find_thread(NULL);
  thread_info info;
  get_thread_info(main_thread, &info);
  rename_thread(main_thread, "X Server"); 
  server_thread = spawn_thread(xmain, info.name, B_NORMAL_PRIORITY, 0);
  resume_thread(server_thread);
  suspend_thread(main_thread);
  init_font();
  set_display(display);
  return display;
}
Exemple #9
0
void TToolTipView::AllAttached()
{
	// initialize internal settings
	fTip.app_active = true;
	fTip.quit = false;
	fTip.stopped = true;

	fTip.tool_tip_view = this;
	fTip.tool_tip_window = Window();

	// start tool_tip thread
	resume_thread(fThread = spawn_thread((status_t (*)(void *)) ToolTipThread,
				"tip_thread", B_DISPLAY_PRIORITY, &fTip));
}
Exemple #10
0
// ---------------------------------------------------------------
// StartPrintThread
//
// Sets the status of the current spool job to "processing" and
// starts the print_thread.
// ---------------------------------------------------------------
void 
Printer::StartPrintThread()
{
	Acquire();
	thread_id tid = spawn_thread(print_thread, "print", B_NORMAL_PRIORITY, (void*)fJob);
	if (tid > 0) {
		fJob->SetStatus(kProcessing);
		atomic_add(&fProcessing, 1);
		resume_thread(tid);
	} else {
		fJob->Release();
		Release();
	}
}
void
ThemeInterfaceView::PopulateThemeList()
{
	int i;
	BControl *c;
	for (i = 0; ChildAt(i); i++) {
		c = dynamic_cast<BControl *>(ChildAt(i));
		if (c)
			c->SetEnabled(false);
	}
	thread_id tid = spawn_thread(_ThemeListPopulatorTh, "ThemeListPopulator", 
		B_LOW_PRIORITY, this);
	resume_thread(tid);
}
Exemple #12
0
DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
{
    thread_id NativeThread;
    RT_ASSERT_PREEMPTIBLE();

    NativeThread = spawn_kernel_thread(rtThreadNativeMain, pThreadInt->szName, B_NORMAL_PRIORITY, pThreadInt);
    if (NativeThread >= B_OK)
    {
        resume_thread(NativeThread);
        *pNativeThread = (RTNATIVETHREAD)NativeThread;
        return VINF_SUCCESS;
    }
    return RTErrConvertFromHaikuKernReturn(NativeThread);
}
Exemple #13
0
void
FindWindow::SpawnThread(int8 findMode)
{
	AbortThread();
	
	fThreadID = spawn_thread(FinderThread, "search_thread", B_NORMAL_PRIORITY, this);
	if (fThreadID > 0)
	{
		fThreadMode = findMode;
		resume_thread(fThreadID);
	}
	else
		fThreadID = -1;
}
void
SyslogDaemon::ReadyToRun()
{
	fPort = create_port(256, SYSLOG_PORT_NAME);
	fDaemon = spawn_thread(daemon_thread, "daemon", B_NORMAL_PRIORITY, this);

	if (fPort >= B_OK && fDaemon >= B_OK) {
		init_syslog_output(this);
		init_listener_output(this);

		resume_thread(fDaemon);
	} else
		Quit();
}
AutoMounter::AutoMounter(bool _DEVICE_MAP_ONLY(checkRemovableOnly),
	bool _DEVICE_MAP_ONLY(checkCDs), bool _DEVICE_MAP_ONLY(checkFloppies),
	bool _DEVICE_MAP_ONLY(checkOtherRemovable), bool _DEVICE_MAP_ONLY(autoMountRemovablesOnly),
	bool _DEVICE_MAP_ONLY(autoMountAll), bool _DEVICE_MAP_ONLY(autoMountAllBFS),
	bool _DEVICE_MAP_ONLY(autoMountAllHFS),
	bool initialMountAll, bool initialMountAllBFS, bool initialMountRestore,
	bool initialMountAllHFS)
	:	BLooper("DirPoller", B_LOW_PRIORITY),
		fInitialMountAll(initialMountAll),
		fInitialMountAllBFS(initialMountAllBFS),
		fInitialMountRestore(initialMountRestore),
		fInitialMountAllHFS(initialMountAllHFS),
		fSuspended(false),
		fQuitting(false)
{
#if _INCLUDES_CLASS_DEVICE_MAP
	fScanParams.shortestRescanHartbeat = 5000000;
	fScanParams.checkFloppies = checkFloppies;
	fScanParams.checkCDROMs = checkCDs;
	fScanParams.checkOtherRemovable = checkOtherRemovable;
	fScanParams.removableOrUnknownOnly = checkRemovableOnly;
	
	fAutomountParams.mountAllFS = autoMountAll;
	fAutomountParams.mountBFS = autoMountAllBFS;
	fAutomountParams.mountHFS = autoMountAllHFS;
	fAutomountParams.mountRemovableDisksOnly = autoMountRemovablesOnly;

	gSilentAutoMounter = true;
	
	if (!BootedInSafeMode()) {
		ReadSettings();
		thread_id rescan = spawn_thread(AutoMounter::InitialRescanBinder, 
			"AutomountInitialScan", B_DISPLAY_PRIORITY, this);
		resume_thread(rescan);
	} else {
		// defeat automounter in safe mode, don't even care about the settings
		fAutomountParams.mountAllFS = false;
		fAutomountParams.mountBFS = false;
		fAutomountParams.mountHFS = false;
		fInitialMountAll = false;
		fInitialMountAllBFS = false;
		fInitialMountRestore = false;
		fInitialMountAllHFS = false;
	}

	//	Watch mount/unmount
	TTracker::WatchNode(0, B_WATCH_MOUNT, this);
#endif
}
void SnowView::AttachedToWindow()
{
	BView *p;
	rgb_color col;
	fAttached = true;
/*	if (!fMsgRunner)
		fMsgRunner = new BMessageRunner(BMessenger(this), 
					new BMessage(MSG_PULSE_ME), 
					INTERVAL);
*/
	p = Parent();
	if (p)
		col = B_TRANSPARENT_32_BIT;//Parent()->ViewColor();
	else
		col = ui_color(B_PANEL_BACKGROUND_COLOR);
	SetViewColor(col);
//	BScreen bs;
//	fCachedWsWidth = bs.Frame().IntegerWidth();
//	fCachedWsHeight = bs.Frame().IntegerHeight();
	fDragger = dynamic_cast<BDragger *>(FindView("_dragger_"));
	if (fDragger && p) {
		fCachedParent = p;
		fCachedWsWidth = p->Frame().IntegerWidth();
		fCachedWsHeight = p->Frame().IntegerHeight();
		fDragger->SetViewColor(col);
		if (fDragger->InShelf()) {
			p->SetFlags(p->Flags() | B_DRAW_ON_CHILDREN);
#ifdef B_BEOS_VERSION_DANO
			p->SetDoubleBuffering(p->DoubleBuffering() | B_UPDATE_EXPOSED);
#endif
			ResizeTo(p->Bounds().Width(), p->Bounds().Height());
			MoveTo(0,0);
			fDragger->MoveTo(p->Bounds().Width()-7, p->Bounds().Height()-7);
		}
		BRect fallenRect(p->Bounds());
		fallenRect.top = fallenRect.bottom - FALLEN_HEIGHT;
		fFallenBmp = new BBitmap(fallenRect, B_BITMAP_ACCEPTS_VIEWS, B_CMAP8);
		memset(fFallenBmp->Bits(), B_TRANSPARENT_MAGIC_CMAP8, (size_t)(fallenRect.Height()*fFallenBmp->BytesPerRow()));
		fFallenView = new BView(fallenRect, "offscreen fallen snow", B_FOLLOW_NONE, 0);
		fFallenBmp->AddChild(fFallenView);
		fFallenReg = new BRegion;
		fInvalidator = spawn_thread(SnowMakerThread, INVALIDATOR_THREAD_NAME, B_LOW_PRIORITY, (void *)this);
		resume_thread(fInvalidator);
		printf("BSnow: OK: ws = %ld x %ld\n", fCachedWsWidth, fCachedWsHeight);
#ifdef DEBUG
		Window()->AddCommonFilter(new BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE, msgfilter));
#endif
	}
}
Exemple #17
0
void
MediaWindow::MessageReceived(BMessage* message)
{
	switch (message->what) {
		case ML_RESTART_THREAD_FINISHED:
			fRestartThread = -1;
			_InitMedia(false);
			break;

		case ML_RESTART_MEDIA_SERVER:
		{
			fRestartThread = spawn_thread(&MediaWindow::_RestartMediaServices,
				"restart_thread", B_NORMAL_PRIORITY, this);
			if (fRestartThread < 0)
				fprintf(stderr, "couldn't create restart thread\n");
			else
				resume_thread(fRestartThread);
			break;
		}

		case B_MEDIA_WEB_CHANGED:
		case ML_SELECTED_NODE:
		{
			PRINT_OBJECT(*message);

			MediaListItem* item = static_cast<MediaListItem*>(
					fListView->ItemAt(fListView->CurrentSelection()));
			if (item == NULL)
				break;

			fCurrentNode.SetTo(NULL);
			_ClearParamView();
			item->AlterWindow(this);
			break;
		}

		case B_MEDIA_SERVER_STARTED:
		case B_MEDIA_SERVER_QUIT:
		{
			PRINT_OBJECT(*message);
			_InitMedia(false);
			break;
		}

		default:
			BWindow::MessageReceived(message);
			break;
	}
}
Exemple #18
0
status_t NNTPResponse::Read(Logger* logger)
{
	BAutolock(this);

	// set up & read the first buffer
	firstBuffer = new RespBuffer(multiline ? LargeBufferSize : MaxStatusRespSize);
	lastBuffer = firstBuffer;
	status_t result = connection->ReadBuffer(firstBuffer);
	if (result != B_NO_ERROR)
		return result;

	// log the response
	if (logger) {
		logger->Log(NextLine());
		Reset();
		}

	// get the result code and set "multiline" based on it
	// we need this before we can call IsFinalBuffer()
	result = NextIntField();
	switch (result) {
		case 100:	case 215:	case 218:	case 220:	case 221:	case 222:	case 224:
		case 230:	case 231:	case 282:	case 288:
			multiline = true;
			break;

		default:
			multiline = false;
			break;
		}

	// if that's all, we're done
	if (IsFinalBuffer(firstBuffer))
		return result;

	// otherwise, start reading the rest of the buffers
	RespBuffer* nextBuffer = new RespBuffer(LargeBufferSize);
	SpillBuffer(firstBuffer, nextBuffer);
	NNTPResponseThreadParams* threadParams = new NNTPResponseThreadParams(this, nextBuffer);
	readerThread =
		spawn_thread(ThreadStarter, "NNTPResponse reader", B_NORMAL_PRIORITY, threadParams);
	if (readerThread < 0) {
		delete threadParams;
		return readerThread;
		}
	resume_thread(readerThread);

	return result;
}
Exemple #19
0
void
TMagnify::AttachedToWindow()
{
	int32 width, height;
	fParent->PixelCount(&width, &height);
	InitBuffers(width, height, fParent->PixelSize(), fParent->ShowGrid());

	fThread = spawn_thread(TMagnify::MagnifyTask, "MagnifyTask",
		B_NORMAL_PRIORITY, this);

	resume_thread(fThread);

	SetViewColor(B_TRANSPARENT_32_BIT);
	MakeFocus();
}
Exemple #20
0
// Run
status_t
Task::Run()
{
	const char* name = (fName.GetLength() > 0 ? fName.GetString() : "task");
#if USER
	fThread = spawn_thread(&_ThreadEntry, name, B_NORMAL_PRIORITY, this);
#else
	fThread = spawn_kernel_thread(&_ThreadEntry, name, B_NORMAL_PRIORITY, this);
#endif
	if (fThread < 0)
		return fThread;
	fDone = false;
	resume_thread(fThread);
	return B_OK;
}
Exemple #21
0
//------------------------------------------------------------------------------
void BMenuField::MouseDown(BPoint where)
{
	if (where.x > fDivider && !fMenuBar->Frame().Contains(where))
		return;

	BRect bounds = fMenuBar->ConvertFromParent(Bounds());

	fMenuBar->StartMenuBar(0, false, true, &bounds);

	fMenuTaskID = spawn_thread((thread_func)MenuTask, "_m_task_",
		B_NORMAL_PRIORITY, this);

	if (fMenuTaskID)
		resume_thread(fMenuTaskID);
}
Exemple #22
0
void	
QueueActions::AddAction(Action* a){

	//FIX!
	//esiste già un azione con lo stesso ID???
	
	if(Lock()){
		printf("adding %ld - Action name %s\n",fID,a->GetDescription().String());
		fList.AddItem(a);
		if(fList.CountItems() == 1) //Auto-start thread
			resume_thread(fID);
			
	Unlock();
	}
}
/*static*/ void
TermApp::_SigChildHandler(int signal, void* data)
{
	// Spawing a thread that does the actual signal handling is pretty much
	// the only safe thing to do in a multi-threaded application. The
	// interrupted thread might have been anywhere, e.g. in a critical section,
	// holding locks. If we do anything that does require locking at any point
	// (e.g. memory allocation, messaging), we risk a dead-lock or data
	// structure corruption. Spawing a thread is safe though, since its only
	// a system call.
	thread_id thread = spawn_thread(_ChildCleanupThread, "child cleanup",
		B_NORMAL_PRIORITY, ((TermApp*)data)->fTermWindow);
	if (thread >= 0)
		resume_thread(thread);
}
Exemple #24
0
void nsToolkit::RunPump(void* arg)
{
  int32		code;
  char		portname[64];
  ThreadInterfaceData id;

  ThreadInitInfo *info = (ThreadInitInfo*)arg;
  PR_EnterMonitor(info->monitor);

  gThreadState = PR_TRUE;

  PR_Notify(info->monitor);
  PR_ExitMonitor(info->monitor);

  delete info;

  // system wide unique names
  PR_snprintf(portname, sizeof(portname), "event%lx", 
              (long unsigned) PR_GetCurrentThread());

  port_id event = create_port(100, portname);

  while(read_port(event, &code, &id, sizeof(id)) >= 0)
  {
    switch(code)
    {
      case WM_CALLMETHOD :
        {
          MethodInfo *mInfo = (MethodInfo *)id.data;
          mInfo->Invoke();
          if(id.waitingThread != 0)
            resume_thread(id.waitingThread);
          delete mInfo;
        }
        break;
      case 'natv' :	// native queue PLEvent
        {
          PREventQueue *queue = (PREventQueue *)id.data;
          PR_ProcessPendingEvents(queue);
        }
        break;

      default :
        printf("nsToolkit::RunPump - UNKNOWN EVENT\n");
        break;
    }
  }
}
extern "C" int be_mouse_init(void)
{
   sem_id mouse_started;
   int32  num_buttons;

   mouse_started = create_sem(0, "starting mouse driver...");

   if (mouse_started < 0) {
      goto cleanup;
   }

   mouse_thread_id = spawn_thread(mouse_thread, MOUSE_THREAD_NAME,
                        MOUSE_THREAD_PRIORITY, &mouse_started); 

   if (mouse_thread_id < 0) {
      goto cleanup;
   }

   mouse_thread_running = true;
   resume_thread(mouse_thread_id);
   acquire_sem(mouse_started);
   delete_sem(mouse_started);

   be_mickey_x = 0;
   be_mickey_y = 0;

   be_mouse_x = 0;
   be_mouse_y = 0;
   be_mouse_b = 0;

   limit_up     = 0;
   limit_down   = 0;
   limit_left   = 0;
   limit_right  = 0;

   get_mouse_type(&num_buttons);

   return num_buttons;

   cleanup: {
      if (mouse_started > 0) {
         delete_sem(mouse_started);
      }

      be_mouse_exit();
      return 0;
   }
}
void TVideoPreviewView::Init()
{
	// We don't need a background color
	SetViewColor(B_TRANSPARENT_32_BIT);

	AddNodeKind(B_PHYSICAL_OUTPUT);

	mPort                           = create_port(3, "TVideoPreviewView input");
	mDestination.port       = mPort;
	mDestination.id         = 0;
	mLast                           = 0;

	mRunMode = B_DROP_DATA;

	m_Bitmap = NULL;

	vThread = 0;
	mThread = 0;

	mControlQuit = false;
	mDisplayQuit = false;

	mConnected      = false;
	mRunning        = false;
	mStarting       = false;
	mStopping       = false;
	mSeeking        = false;

	mStartTime      = 0;            /* when to start in performance time */
	mStopTime       = 0;            /* when to stop in performance time */
	mSeekTime       = 0;
	mMediaTime      = 0;
	mDeltaTime      = 0;

	mMyLatency                      = 10000;
	mDownstreamLatency      = 0;

	mBufferAvailable = 0;

	mServiceLock = create_sem (1, "Video Consumer Service Lock");
	if (mServiceLock < B_NO_ERROR) {
		ERROR("TVideoPreviewView: couldn't create ServiceLock semaphore\n");
	}

	mThread = spawn_thread(sRun, "TVideoPreviewView:run", B_REAL_TIME_PRIORITY, this);
	resume_thread(mThread);

}
Exemple #27
0
status_t
SerialDevice::Open(uint32 flags)
{
	if (fDeviceOpen)
		return B_BUSY;

	if (fDeviceRemoved)
		return B_DEV_NOT_READY;

	gTTYModule->ttyinit(&fTTY, true);
	fTTYFile.tty = &fTTY;
	fTTYFile.flags = flags;
	ResetDevice();

	struct ddrover *ddr = gTTYModule->ddrstart(NULL);
	if (!ddr)
		return B_NO_MEMORY;

	gTTYModule->ddacquire(ddr, &gSerialDomain);
	status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, usb_serial_service);
	gTTYModule->ddrdone(ddr);

	if (status < B_OK) {
		TRACE_ALWAYS("open: failed to open tty\n");
		return status;
	}

	fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread",
		B_NORMAL_PRIORITY, this);

	if (fDeviceThread < B_OK) {
		TRACE_ALWAYS("open: failed to spawn kernel thread\n");
		return fDeviceThread;
	}

	resume_thread(fDeviceThread);

	fControlOut = CLS_LINE_DTR | CLS_LINE_RTS;
	SetControlLineState(fControlOut);

	status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer,
		fInterruptBufferSize, InterruptCallbackFunction, this);
	if (status < B_OK)
		TRACE_ALWAYS("failed to queue initial interrupt\n");

	fDeviceOpen = true;
	return B_OK;
}
Exemple #28
0
int main(int argc, char **argv) {
    int32 status, i;
    thread_id foo;
    data bar;
    char *name;
    bar.id = strtoul(argv[1], NULL, 0);
    bar.name = (char *) malloc(1024);
    foo = spawn_thread(find_proc, "find_proc", B_REAL_TIME_PRIORITY, &bar);
    resume_thread(foo);
    wait_for_thread(foo, &status);
    if(status)
        printf("%s\n", bar.name);
    else
        printf("Failed.\n");
    return 0;
}
Exemple #29
0
status_t CommandThread::Run()
{
	AutoLocker<CommandThread> locker(this);

	//TODO Check if thread is already running

	fThread = spawn_thread(CommandThread::_Thread, "command thread", B_NORMAL_PRIORITY, this);
	if (fThread < B_OK)
		return B_ERROR;

	if (resume_thread(fThread) != B_OK)
		return B_ERROR;

	started = true;
	return B_OK;
}
GenerateSudoku::GenerateSudoku(SudokuField& field, int32 level,
		BMessenger progress, BMessenger target)
	:
	fField(field),
	fTarget(target),
	fProgress(progress),
	fLevel(level),
	fQuit(false)
{
	fThread = spawn_thread(_GenerateThread, "sudoku generator",
		B_LOW_PRIORITY, this);
	if (fThread >= B_OK)
		resume_thread(fThread);
	else
		_Generate();
}