[rkward-cvs] SF.net SVN: rkward:[3141] branches/2010_10_18_backend_restructuring_branch/ rkward/rbackend

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sun Oct 24 19:05:09 UTC 2010


Revision: 3141
          http://rkward.svn.sourceforge.net/rkward/?rev=3141&view=rev
Author:   tfry
Date:     2010-10-24 19:05:08 +0000 (Sun, 24 Oct 2010)

Log Message:
-----------
Completed turning the event loop upside down. Compiles, but does not run, yet.

Modified Paths:
--------------
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.cpp
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.cpp	2010-10-24 12:40:33 UTC (rev 3140)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.cpp	2010-10-24 19:05:08 UTC (rev 3141)
@@ -23,8 +23,6 @@
 #include "../debug.h"
 #include "../rkglobals.h"
 
-#define MAX_RECEIVERS 3
-
 RCommandBase::RCommandBase (bool is_chain) {
 	is_command_chain = is_chain;
 	RCommandBase::parent = 0;
@@ -57,8 +55,7 @@
 	if (_command.isEmpty ()) _type |= EmptyCommand;
 	status = 0;
 	_rk_equiv = rk_equiv;
-	RCommand::receivers = new RCommandReceiver* [MAX_RECEIVERS];
-	num_receivers = 0;
+	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) receivers[i] = 0;
 	if (!(type & Internal)) {
 		addReceiver (receiver);
 		addReceiver (RKCommandLog::getLog ());
@@ -71,7 +68,6 @@
 	for (QList<ROutput*>::const_iterator it = output_list.constBegin (); it != output_list.constEnd (); ++it) {
 		delete (*it);
 	}
-	delete [] receivers;
 	// The output_list itself is cleared automatically
 }
 
@@ -80,13 +76,15 @@
 
 	if (!receiver) return;
 
-	if (num_receivers >= MAX_RECEIVERS) {
-		RK_DO (qDebug ("Too many receivers for command"), RBACKEND, DL_ERROR);
-		return;
+	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
+		if (receivers[i] == 0) {
+			receivers[i] = receiver;
+			receiver->addCommand (this);
+			return;
+		}
 	}
 
-	receivers[num_receivers++] = receiver;
-	receiver->addCommand (this);
+	RK_DO (qDebug ("Too many receivers for command"), RBACKEND, DL_ERROR);
 }
 
 void RCommand::removeReceiver (RCommandReceiver *receiver) {
@@ -94,27 +92,21 @@
 
 	if (!receiver) return;
 
-	RCommandReceiver **newlist = new RCommandReceiver* [MAX_RECEIVERS];
-	int num_new_receivers = 0;
-	for (int i=0; i < num_receivers; ++i) {
-		if (receivers[i] != receiver) {
-			newlist[num_new_receivers++] = receivers[i];
+	for (int i = 0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
+		if (receivers[i] == receiver) {
+			receivers[i] = 0;
+			return;
 		}
 	}
 
-	if (num_new_receivers == num_receivers) {
-		RK_DO (qDebug ("Was not a receiver in RCommand::removeReceiver"), RBACKEND, DL_WARNING);
-	}
-
-	delete [] receivers;
-	receivers = newlist;
-	num_receivers = num_new_receivers;
+	RK_DO (qDebug ("Was not a receiver in RCommand::removeReceiver: %p", receiver), RBACKEND, DL_WARNING);
 }
 
 void RCommand::finished () {
 	RK_TRACE (RBACKEND);
 
-	for (int i=0; i < num_receivers; ++i) {
+	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
+		if (receivers[i] == 0) continue;
 		receivers[i]->delCommand (this);
 		receivers[i]->rCommandDone (this);
 	}
@@ -123,7 +115,8 @@
 void RCommand::newOutput (ROutput *output) {
 	RK_TRACE (RBACKEND);
 
-	for (int i=0; i < num_receivers; ++i) {
+	for (int i=0; i < MAX_RECEIVERS_PER_RCOMMAND; ++i) {
+		if (receivers[i] == 0) continue;
 		receivers[i]->newOutput (this, output);
 	}
 }

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h	2010-10-24 12:40:33 UTC (rev 3140)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h	2010-10-24 19:05:08 UTC (rev 3141)
@@ -2,7 +2,7 @@
                           rcommand.h  -  description
                              -------------------
     begin                : Mon Nov 11 2002
-    copyright            : (C) 2002, 2006, 2007, 2009 by Thomas Friedrichsmeier
+    copyright            : (C) 2002, 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
     email                : tfry at users.sourceforge.net
  ***************************************************************************/
 
@@ -25,6 +25,8 @@
 
 #include "rdata.h"
 
+#define MAX_RECEIVERS_PER_RCOMMAND 3
+
 class RCommandReceiver;
 class RCommand;
 class RCommandChain;
@@ -73,24 +75,6 @@
 
 typedef QList<ROutput*> ROutputList;
 
-/*
-struct RGetValueRequest {
-private:
-friend class RInterface;
-friend class RThread;
-	char **call;
-	int call_length;
-};
-
-struct RGetValueReply {
-private:
-friend class RInterface;
-friend class RThread;
-	char **reply;
-	int reply_length;
-};
-*/
-
 /** For introductory information on using RCommand, see \ref UsingTheInterfaceToR 
 
 	This class is used to encapsulate an R-command, so it can be easily identified
@@ -221,8 +205,7 @@
 	QString _rk_equiv;
 	int _id;
 	static int next_id;
-	int num_receivers;
-	RCommandReceiver **receivers;
+	RCommandReceiver *receivers[MAX_RECEIVERS_PER_RCOMMAND];
 };
 
 #endif

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-24 12:40:33 UTC (rev 3140)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-24 19:05:08 UTC (rev 3141)
@@ -19,7 +19,7 @@
 
 // static
 RThread *RThread::this_pointer = 0;
-RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, RThread::RKReplStatus::NoUserCommand, 0 };
+RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0 };
 
 #include <qstring.h>
 #include <QStringList>
@@ -134,13 +134,19 @@
 	if (RThread::repl_status.eval_depth == 0) {
 		RK_ASSERT (RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandRunning);
 		if (succeeded) {
-			RThread::repl_status.user_command_successful_up_to = RThread::repl_status.user_command_transmitted_up_to;
+			RThread::repl_status.user_command_successful_up_to = RThread::repl_status.user_command_parsed_up_to;
 			if (RThread::repl_status.user_command_completely_transmitted) RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
 			else RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandTransmitted;
 		} else {
 			// skip remainder of command
 			RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
 		}
+		if (RThread::repl_status.user_command_status == RThread::RKReplStatus::NoUserCommand) {
+			MUTEX_LOCK;
+			if (!succeeded) RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
+			MUTEX_UNLOCK;
+			RThread::this_pointer->commandFinished ();
+		}
 	}
 	
 	return (Rboolean) true;
@@ -191,17 +197,28 @@
 	if (RThread::repl_status.eval_depth == 0) {
 		if (RThread::repl_status.user_command_status == RThread::RKReplStatus::NoUserCommand) {
 			MUTEX_LOCK;
-			RCommand *command = RThread::this_pointer->fetchNextCommand ();
+			RCommand *command = RThread::this_pointer->fetchNextCommand (RCommandStack::regular_stack);
+			if (!command) return 0;	// jumps out of the event loop!
+
+			RThread::this_pointer->current_command = command;
 			if (!(command->type () & RCommand::User)) {
 				RThread::this_pointer->runCommand (command);
+				RThread::this_pointer->commandFinished ();
 				MUTEX_UNLOCK;
 			} else {
 				// so, we are about to transmit a new user command, which is quite a complex endeavour...
+				/* Some words about running user commands:
+				- User commands can only be run at the top level of execution, not in any sub-stacks. But then, they should never get there, in the first place.
+				- Handling user commands is totally different from all other commands, and relies on R's "REPL" (read-evaluate-print-loop). This is a whole bunch of dedicated code, but there is no other way to achieve handling of commands as if they had been entered on a plain R console (incluing auto-printing, and toplevel handlers). Most importantly, since important symbols are not exported, such as R_Visible. Vice versa, it is not possible to treat all commands like user commands, esp. in substacks.
+
+				Problems to deal with:
+				- R_ReadConsole serves a lot of different functions, including reading in code, but also handling user input for readline() or browser(). This makes it necessary to carefully track the current status using "repl_status". You will find repl_status to be modified at a couple of different functions.
+				*/
 				RThread::repl_status.user_command_transmitted_up_to = 0;
 				RThread::repl_status.user_command_completely_transmitted = false;
+				RThread::repl_status.user_command_parsed_up_to = 0;
 				RThread::repl_status.user_command_successful_up_to = 0;
 				RThread::repl_status.user_command_buffer = RThread::this_pointer->current_locale_codec->fromUnicode (command->command ());
-				RThread::this_pointer->current_command = command;
 				MUTEX_UNLOCK;
 				RKTransmitNextUserCommandChunk (buf, buflen);
 				RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandTransmitted;
@@ -212,7 +229,7 @@
 			if (RThread::repl_status.user_command_completely_transmitted) {
 				// fully transmitted, but R is still asking for more? -> Incomplete statement
 				MUTEX_LOCK;
-				RThread::this_pointer->current_command->status |= RCommand::ErrorIncomplete;
+				RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorIncomplete;
 				RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
 				MUTEX_UNLOCK;
 			} else {
@@ -222,7 +239,7 @@
 			return 1;
 		} else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandSyntaxError) {
 			MUTEX_LOCK;
-			RThread::this_pointer->current_command->status |= RCommand::ErrorIncomplete;
+			RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorSyntax;
 			RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
 			MUTEX_UNLOCK;
 			buf[0] = '\0';
@@ -239,7 +256,7 @@
 	}
 	
 	// here, we handle readline() calls and such, i.e. not the regular prompt for code
-	// browser() also takes us here. TODO: give browser() special handling!
+	// browser() also takes us here. TODO: give browser() special handling! May be identifiable due to hist==true
 	RCallbackArgs args;
 	args.type = RCallbackArgs::RReadLine;
 	args.params["prompt"] = QVariant (prompt);
@@ -487,6 +504,7 @@
 	// R_ReplIteration calls R_Busy (1) after reading in code (if needed), successfully parsing it, and right before evaluating it.
 	if (busy) {
 		if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandTransmitted) {
+			RThread::repl_status.user_command_parsed_up_to = RThread::repl_status.user_command_transmitted_up_to;
 			RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandRunning;
 		}
 	}
@@ -509,6 +527,7 @@
 	current_output = 0;
 	out_buf_len = 0;
 	output_paused = false;
+	previously_idle = false;
 
 #ifdef Q_WS_WIN
 	// we hope that on other platforms the default is reasonable
@@ -947,7 +966,6 @@
 #endif
 
 	RKGlobals::na_double = NA_REAL;
-	R_ReplDLLinit ();
 
 	RKWard_RData_Tag = Rf_install ("RKWard_RData_Tag");
 	R_LastvalueSymbol = Rf_install (".Last.value");
@@ -1137,59 +1155,38 @@
 	QByteArray ccommand = current_locale_codec->fromUnicode (command->command ());
 	RData retdata;
 
+	// running user commands is quite different from all other commands and should have been handled by RReadConsole
+	RK_ASSERT (!(ctype & RCommand::User));
+
 	if (!(ctype & RCommand::Internal)) {
 		MUTEX_UNLOCK;
 	}
-	// running user commands is quite different from all other commands
-	if (ctype & RCommand::User) {
-#error restructure, move this, keep comment
-	  // run a user command
-/* Using R_ReplDLLdo1 () is a pain, but it seems to be the only entry point for evaluating a command as if it had been entered on a plain R console (with auto-printing if not invisible, etc.). Esp. since R_Visible is no longer exported in R 2.5.0, as it seems as of today (2007-01-17).
 
-Problems to deal with:
-- R_ReplDLLdo1 () may do a jump on an error. Hence we need R_ToplevelExec (public sind R 2.4.0)
-	- this is why runUserCommandInternal needs to be a separate function
-- R_ReplDLLdo1 () expects to receive the code input via R_ReadConsole. The same R_ReadConsole that commands like readline () or browser () will use to get their input.
-	- hence we need some state variables to figure out, when a call to R_ReadConsole originates directly from R_ReplDLLdo1 (), or some R statement. R_Busy () is our friend, here.
-- R_ReplDLLdo1 () will only ever evaluate one statement, even if several statements have already been transfered to the buffer. In fact, it will even return once after each ';' or '\n', even if the statement is not complete, but more is already in the buffer
-	- Hence we need two loops around R_ReplDLLdo1 (): one to make sure it continues reading until a statement is actually complete, another to continue if there is a second (complete or incomplete) statement in the command
-	- Also, in case the command was too long to fit inside the buffer at once (repldll_buffer_transfer_finished)
-- Some more state variables are used for figuring out, which type of error occurred, if any, since we don't get any decent return value
-
-This is the logic spread out over the following section, runUserCommandInternal (), and RReadConsole (). 
-
-NOTE from Deepayan Sarkar: Another possible simplification (which may not be worth doing
-ultimately): you distinguish between two types of calls to
-R_ReadConsole based on R_busy calls, but you may be able to use the
-second 'hist' argument. I didn't look too carefully, but it seems like
-hist == 1 iff R wants a parse-able input.
-*/
-	} else {		// not a user command
-		repl_status.eval_depth++;
-		SEXP parsed = parseCommand (command->command (), &error);
+	repl_status.eval_depth++;
+	SEXP parsed = parseCommand (command->command (), &error);
+	if (error == NoError) {
+		SEXP exp;
+		PROTECT (exp = runCommandInternalBase (parsed, &error));
 		if (error == NoError) {
-			SEXP exp;
-			PROTECT (exp = runCommandInternalBase (parsed, &error));
-			if (error == NoError) {
-				if (ctype & RCommand::GetStringVector) {
-					retdata.datatype = RData::StringVector;
-					retdata.data = SEXPToStringList (exp, &(retdata.length));
-				} else if (ctype & RCommand::GetRealVector) {
-					retdata.datatype = RData::RealVector;
-					retdata.data = SEXPToRealArray (exp, &(retdata.length));
-				} else if (ctype & RCommand::GetIntVector) {
-					retdata.datatype = RData::IntVector;
-					retdata.data = SEXPToIntArray (exp, &(retdata.length));
-				} else if (ctype & RCommand::GetStructuredData) {
-					RData *dummy = SEXPToRData (exp);
-					retdata.setData (*dummy);
-					delete dummy;
-				}
+			if (ctype & RCommand::GetStringVector) {
+				retdata.datatype = RData::StringVector;
+				retdata.data = SEXPToStringList (exp, &(retdata.length));
+			} else if (ctype & RCommand::GetRealVector) {
+				retdata.datatype = RData::RealVector;
+				retdata.data = SEXPToRealArray (exp, &(retdata.length));
+			} else if (ctype & RCommand::GetIntVector) {
+				retdata.datatype = RData::IntVector;
+				retdata.data = SEXPToIntArray (exp, &(retdata.length));
+			} else if (ctype & RCommand::GetStructuredData) {
+				RData *dummy = SEXPToRData (exp);
+				retdata.setData (*dummy);
+				delete dummy;
 			}
-			UNPROTECT (1); // exp
 		}
-		repl_status.eval_depth--;
+		UNPROTECT (1); // exp
 	}
+	repl_status.eval_depth--;
+
 	if (!(ctype & RCommand::Internal)) {
 		if (!locked || killed) processX11Events ();
 		MUTEX_LOCK;

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-24 12:40:33 UTC (rev 3140)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-24 19:05:08 UTC (rev 3141)
@@ -255,6 +255,7 @@
 		QByteArray user_command_buffer;
 		int user_command_transmitted_up_to;
 		bool user_command_completely_transmitted;
+		int user_command_parsed_up_to;
 		int user_command_successful_up_to;
 		enum {
 			NoUserCommand,
@@ -265,11 +266,16 @@
 		int eval_depth;		// Number (depth) of non-user commands currently running. User commands can only run at depth 0
 	};
 	static RKReplStatus repl_status;
+
+	// fetch next command (and do event processing while waiting)
+	RCommand *fetchNextCommand (RCommandStack *stack);
+	void commandFinished ();
 protected:
 /** thread is locked. No new commands will be executed. @see LockType @see lock @see unlock */
 	int locked;
 /** thread is killed. Should exit as soon as possible. @see kill */
 	bool killed;
+	bool previously_idle;
 /** On pthread systems this is the pthread_id of the backend thread. It is needed to send SIGINT to the R backend */
 	Qt::HANDLE thread_id;
 private:

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp	2010-10-24 12:40:33 UTC (rev 3140)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp	2010-10-24 19:05:08 UTC (rev 3141)
@@ -57,7 +57,6 @@
 	locked = Startup;
 	killed = false;
 	int err;
-	bool previously_idle = false;
 
 	// in RInterface::RInterface() we create a fake RCommand to capture all the output/errors during startup
 	MUTEX_LOCK;
@@ -86,7 +85,36 @@
 	notifyCommandDone (current_command);
 	MUTEX_UNLOCK;
 
+	enterEventLoop ();
+}
+
+void RThread::commandFinished () {
+	RK_TRACE (RBACKEND);
+
+	RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG);
+	MUTEX_LOCK;
+	current_command->status -= (current_command->status & RCommand::Running);
+	current_command->status |= RCommand::WasTried;
+	RCommandStackModel::getModel ()->itemChange (current_command);
+
+	checkObjectUpdatesNeeded (current_command->type () & (RCommand::User | RCommand::ObjectListUpdate));
+	RCommandStack::currentStack ()->pop ();
+	notifyCommandDone (current_command);	// command may be deleted after this
+
+	all_current_commands.pop_back();
+	current_command = all_current_commands.last ();
+	MUTEX_UNLOCK;
+}
+
+RCommand* RThread::fetchNextCommand (RCommandStack* stack) {
+	RK_TRACE (RBACKEND);
+
+#warning We would need so much less mutex locking everywhere, if the command would simply be copied between threads!
 	while (1) {
+		if (killed) {
+			return 0;
+		}
+
 		processX11Events ();
 
 		MUTEX_LOCK;
@@ -96,26 +124,44 @@
 				previously_idle = false;
 			}
 		}
-	
-		// while commands are in queue, don't wait
-		while ((!locked) && RCommandStack::regular_stack->isActive ()) {
-			current_command = RCommandStack::regular_stack->currentCommand ();
-			
-			if (current_command) {
-				// mutex will be unlocked inside
-				doCommand (current_command);
-				checkObjectUpdatesNeeded (current_command->type () & (RCommand::User | RCommand::ObjectListUpdate));
-				RCommandStack::regular_stack->pop ();
-				notifyCommandDone (current_command);	// command may be deleted after this
+
+		if ((!locked) && stack->isActive ()) {
+			RCommand *command = stack->currentCommand ();
+
+			if (command) {
+				// notify GUI-thread that a new command is being tried and initialize
+				RKRBackendEvent* event = new RKRBackendEvent (RKRBackendEvent::RCommandIn, command);
+				qApp->postEvent (RKGlobals::rInterface (), event);
+				all_current_commands.append (command);
+
+				if ((command->type () & RCommand::EmptyCommand) || (command->status & RCommand::Canceled) || (command->type () & RCommand::QuitCommand)) {
+					// some commands are not actually run by R, but handled inline, here
+					if (command->status & RCommand::Canceled) {
+						command->status |= RCommand::Failed;
+					} else if (command->type () & RCommand::QuitCommand) {
+						killed = true;
+						MUTEX_UNLOCK;
+						shutdown (false);
+						MUTEX_LOCK;		// I guess we don't get here, though?
+					}
+					commandFinished ();
+				} else {
+					RK_DO (qDebug ("running command: %s", command->command ().toLatin1().data ()), RBACKEND, DL_DEBUG);
+				
+					command->status |= RCommand::Running;	// it is important that this happens before the Mutex is unlocked!
+					RCommandStackModel::getModel ()->itemChange (command);
+
+					MUTEX_UNLOCK;
+					return command;
+				}
 			}
-		
-			if (killed) {
-				shutdown (false);
-				MUTEX_UNLOCK;
-				return;
-			}
 		}
 
+		if ((!stack->isActive ()) && stack->isEmpty () && stack != RCommandStack::regular_stack) {
+			MUTEX_UNLOCK;
+			return 0;		// substack depleted
+		}
+
 		if (!previously_idle) {
 			if (RCommandStack::regular_stack->isEmpty ()) {
 				qApp->postEvent (RKGlobals::rInterface (), new RKRBackendEvent (RKRBackendEvent::RIdle));
@@ -127,32 +173,22 @@
 		MUTEX_UNLOCK;
 		if (killed) {
 			shutdown (false);
-			return;
+			return 0;
 		}
-		current_command = 0;
 		msleep (10);
 	}
+
+	return 0;
 }
 
 void RThread::doCommand (RCommand *command) {
 	RK_TRACE (RBACKEND);
-	// step 1: notify GUI-thread that a new command is being tried and initialize
-	RKRBackendEvent* event = new RKRBackendEvent (RKRBackendEvent::RCommandIn, command);
-	qApp->postEvent (RKGlobals::rInterface (), event);
 
 	// step 2: actual handling
 	if (!((command->type () & RCommand::EmptyCommand) || (command->status & RCommand::Canceled))) {
-		all_current_commands.append (command);
 
-		RK_DO (qDebug ("running command: %s", command->command ().toLatin1().data ()), RBACKEND, DL_DEBUG);
-	
-		command->status |= RCommand::Running;	// it is important that this happens before the Mutex is unlocked!
-		RCommandStackModel::getModel ()->itemChange (command);
-
 		runCommand (command);
 	
-		RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG);
-		all_current_commands.pop_back();
 	} else {
 		if (command->status & RCommand::Canceled) {
 			command->status |= RCommand::Failed;
@@ -163,9 +199,6 @@
 			MUTEX_LOCK;
 		}
 	}
-
-	command->status -= (command->status & RCommand::Running);
-	RCommandStackModel::getModel ()->itemChange (command);
 }
 
 
@@ -299,50 +332,20 @@
 		}
 	}
 
-	RCommand *prev_command = current_command;
 	REvalRequest request;
 	request.call = call;
 	MUTEX_LOCK;
 	flushOutput ();
-	RCommandStack *reply_stack = new RCommandStack (prev_command);
+	RCommandStack *reply_stack = new RCommandStack (current_command);
 	request.in_chain = reply_stack->startChain (reply_stack);
 	MUTEX_UNLOCK;
 
 	RKRBackendEvent* event = new RKRBackendEvent (RKRBackendEvent::REvalRequest, &request);
 	qApp->postEvent (RKGlobals::rInterface (), event);
-	
-	bool done = false;
-	while (!done) {
-		processX11Events ();
-		MUTEX_LOCK;
-		// while commands are in queue, don't wait
-		while (reply_stack->isActive ()) {		// substack calls are to be considered "sync", and don't respect locks
-			if (killed) {
-				done = true;
-				break;
-			}
 
-			current_command = reply_stack->currentCommand ();
-			if (current_command) {
-				// mutex will be unlocked inside
-				bool object_update_forced = (current_command->type () & RCommand::ObjectListUpdate);
-				doCommand (current_command);
-				if (object_update_forced) checkObjectUpdatesNeeded (true);
-				reply_stack->pop ();
-				notifyCommandDone (current_command);	// command may be deleted after this
-			} else {
-				msleep (10);
-			}
-		}
-
-		if (reply_stack->isEmpty ()) {
-			done = true;
-		}
-		MUTEX_UNLOCK;
-
-		// if no commands are in queue, sleep for a while
-		current_command = prev_command;
-		msleep (10);
+	RCommand *c;
+	while ((c = fetchNextCommand (reply_stack))) {
+		runCommand (c);
 	}
 
 	MUTEX_LOCK;


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




More information about the rkward-tracker mailing list