[Scummvm-cvs-logs] SF.net SVN: scummvm:[42157] tools/branches/gsoc2009-gui/gui

Remere at users.sourceforge.net Remere at users.sourceforge.net
Mon Jul 6 00:37:28 CEST 2009


Revision: 42157
          http://scummvm.svn.sourceforge.net/scummvm/?rev=42157&view=rev
Author:   Remere
Date:     2009-07-05 22:37:28 +0000 (Sun, 05 Jul 2009)

Log Message:
-----------
*Tool now runs in it's own thread, so it does not halt the GUI while running.
*The text ctrl that is used for output is now enabled, so you can scroll to see all output.

Modified Paths:
--------------
    tools/branches/gsoc2009-gui/gui/pages.cpp
    tools/branches/gsoc2009-gui/gui/pages.h

Modified: tools/branches/gsoc2009-gui/gui/pages.cpp
===================================================================
--- tools/branches/gsoc2009-gui/gui/pages.cpp	2009-07-05 22:16:14 UTC (rev 42156)
+++ tools/branches/gsoc2009-gui/gui/pages.cpp	2009-07-05 22:37:28 UTC (rev 42157)
@@ -849,7 +849,6 @@
 
 ProcessPage::ProcessPage(ScummToolsFrame* frame)
 	: WizardPage(frame),
-	  _success(false),
 	  _finished(false)
 {
 }
@@ -863,10 +862,9 @@
 
 	sizer->Add(new wxStaticText(panel, wxID_ANY, wxT("Processing data...")), wxSizerFlags().Expand().Border(wxLEFT, 20));
 	
-	outwin = new wxTextCtrl(panel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 
+	_outwin = new wxTextCtrl(panel, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, 
 		wxTE_MULTILINE | wxTE_READONLY, wxDefaultValidator, wxT("OutputWindow"));
-	outwin->Enable(false);
-	sizer->Add(outwin, wxSizerFlags(1).Expand().Border(wxALL, 10));
+	sizer->Add(_outwin, wxSizerFlags(1).Expand().Border(wxALL, 10));
 
 	panel->SetSizer(sizer);
 
@@ -876,29 +874,39 @@
 	return panel;
 }
 
-void ProcessPage::writeToOutput(void *udata, const char *text) {
-	ProcessPage *self = reinterpret_cast<ProcessPage *>(udata);
+void ProcessPage::runTool() {
+	const ToolGUI *tool = _topframe->_configuration.selectedTool;
 
-	self->outwin->WriteText(wxString(text, wxConvUTF8));
+	_thread = new ProcessToolThread(tool, _topframe->_configuration, _output);
+
+	// We should check return value of this
+	_thread->Create();
+
+	_thread->Run();
 }
 
-void ProcessPage::runTool() {
-	const ToolGUI *tool = _topframe->_configuration.selectedTool;
-	tool->_backend->setPrintFunction(writeToOutput, reinterpret_cast<void *>(this));
-	try {
-		tool->run(_topframe->_configuration);
-		_success = true;
-	} catch(std::exception &err) {
-		outwin->WriteText(wxString(err.what(), wxConvUTF8));
-		_success = false;
+bool ProcessPage::onIdle(wxPanel *panel) {
+	if(!_thread)
+		return false;
+
+	{
+		wxMutexLocker lock(_output.mutex);
+
+		_outwin->WriteText(wxString(_output.buffer.c_str(), wxConvUTF8));
+
+		_output.buffer = "";
 	}
-	_finished = true;
-}
 
-bool ProcessPage::onIdle(wxPanel *panel) {
-	// TODO
-	// Possibly write stdout to outwin here?
-	return false;
+	// Check if thread finished
+	if(_thread && _thread->_finished) {
+		// It's done, Wait deallocates resources
+		_thread->Wait();
+		delete _thread;
+		_thread = NULL;
+		return false;
+	}
+
+	return true;
 }
 
 void ProcessPage::onNext(wxWindow *panel) {
@@ -918,6 +926,38 @@
 	}
 }
 
+// The thread a tool is run in
+
+ProcessToolThread::ProcessToolThread(const ToolGUI *tool, Configuration &configuration, ThreadOutputBuffer &output) : 
+	wxThread(wxTHREAD_JOINABLE), 
+	_configuration(configuration),
+	_output(output) 
+{
+	_tool = tool;
+	_finished = false;
+	
+	_tool->_backend->setPrintFunction(writeToOutput, reinterpret_cast<void *>(this));
+}
+
+wxThread::ExitCode ProcessToolThread::Entry() {
+	try {
+		_tool->run(_configuration);
+		_output.buffer += "\nTool finished without errors!\n";
+	} catch (ToolException &err) {
+		wxMutexLocker lock(_output.mutex);
+		_output.buffer = _output.buffer + "\nFatal Error Occured: " + err.what() + "\n";
+	}
+	_finished = true;
+	return NULL;
+}
+
+void ProcessToolThread::writeToOutput(void *udata, const char *text) {
+	ProcessToolThread *self = reinterpret_cast<ProcessToolThread *>(udata);
+	
+	wxMutexLocker lock(self->_output.mutex);
+	self->_output.buffer += text;
+}
+
 // Page to choose ANY tool to use
 
 FinishPage::FinishPage(ScummToolsFrame* frame)

Modified: tools/branches/gsoc2009-gui/gui/pages.h
===================================================================
--- tools/branches/gsoc2009-gui/gui/pages.h	2009-07-05 22:16:14 UTC (rev 42156)
+++ tools/branches/gsoc2009-gui/gui/pages.h	2009-07-05 22:37:28 UTC (rev 42157)
@@ -21,10 +21,12 @@
  */
 
 #include <wx/wx.h>
-#include <wx/process.h>
+#include <wx/thread.h>
 
 #include "configuration.h"
 
+class Tool;
+
 /**
  * A backend of a page in the wizard 
  * This class is decoupled from the UI, and you can spawn as many pages as you like from this template
@@ -301,6 +303,50 @@
 
 
 /**
+ * Used for outputting from the subthread
+ * Since the GUI can only be updated from the main thread
+ * We pass this intermediate struct around between main thread
+ * & child thread to update it
+ */
+
+struct ThreadOutputBuffer {
+	std::string buffer;
+	wxMutex mutex;
+};
+
+/**
+ *
+ */
+
+class ProcessToolThread : public wxThread {
+public:
+	ProcessToolThread(const ToolGUI *tool, Configuration &configuration, ThreadOutputBuffer &output);
+
+	/**
+	 * Entry point of the subthread
+	 */
+	virtual ExitCode Entry();
+
+	/**
+	 * Write to the output window pointed to by udata, this adds 
+	 * the message to a locked queue, and prints it to the GUI from 
+	 * the main thread, as doing it from another thread can cause weird bugs.
+	 */
+	static void writeToOutput(void *udata, const char *text);
+
+	bool _finished;
+
+protected:
+	/** The current configuration */
+	Configuration &_configuration;
+	/** */
+	ThreadOutputBuffer &_output;
+	/** */
+	const ToolGUI *_tool;
+};
+
+
+/**
  * Runs the subprocess and displays it's output to the user
  * You can only create one panel from this, unlike the other pages
  * as the class keeps internal state
@@ -313,16 +359,17 @@
 	/** True if the tool has exited */
 	bool _finished;
 	/** Output window */
-	wxTextCtrl *outwin;
+	wxTextCtrl *_outwin;
+	/** The thread which the tool is run in */
+	ProcessToolThread *_thread;
+	/** The structure to exchange output between thread & gui */
+	ThreadOutputBuffer _output;
+
 public:
 	ProcessPage(ScummToolsFrame* frame);
 
 	wxWindow *CreatePanel(wxWindow *parent);
 
-	/**
-	 * Write to the output window pointed to by udata
-	 */
-	static void writeToOutput(void *udata, const char *text);
 
 	/**
 	 * Runs the specified tool, output will be put in outwin


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list