[rkward-cvs] rkward/rkward/rbackend rinterface.cpp, 1.49, 1.50 rthread.cpp, 1.40, 1.41 rthread.h, 1.21, 1.22

Thomas Friedrichsmeier tfry at users.sourceforge.net
Sun Sep 10 23:01:10 UTC 2006


Update of /cvsroot/rkward/rkward/rkward/rbackend
In directory sc8-pr-cvs9.sourceforge.net:/tmp/cvs-serv22080

Modified Files:
	rinterface.cpp rthread.cpp rthread.h 
Log Message:
Use saner output locking, and avoid deadlocks

Index: rinterface.cpp
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rinterface.cpp,v
retrieving revision 1.49
retrieving revision 1.50
diff -C2 -d -r1.49 -r1.50
*** rinterface.cpp	1 Sep 2006 15:38:17 -0000	1.49
--- rinterface.cpp	10 Sep 2006 23:01:07 -0000	1.50
***************
*** 120,127 ****
  
  // TODO: not quite good, yet, leads to staggering output (but overall throughput is the same):
! 	// output events can easily stack up in the hundreds, not allowing GUI events to get through. Let's block further output events for a minute (using MUTEX_LOCK) and then catch up with the event queue
! 		MUTEX_LOCK;
! 		qApp->processEvents ();
! 		MUTEX_UNLOCK;
  	} else if (e->type () == RCOMMAND_IN_EVENT) {
  		watch->addInput (static_cast <RCommand *> (e->data ()));
--- 120,129 ----
  
  // TODO: not quite good, yet, leads to staggering output (but overall throughput is the same):
! 	// output events can easily stack up in the hundreds, not allowing GUI events to get through. Let's block further output events for a minute and then catch up with the event queue
! 		if (qApp->hasPendingEvents ()) {
! 			r_thread->pauseOutput (true);
! 			qApp->processEvents ();
! 			r_thread->pauseOutput (false);
! 		}
  	} else if (e->type () == RCOMMAND_IN_EVENT) {
  		watch->addInput (static_cast <RCommand *> (e->data ()));
***************
*** 155,160 ****
--- 157,164 ----
  		RKGlobals::rkApp ()->setRStatus (true);
  	} else if ((e->type () == R_EVAL_REQUEST_EVENT)) {
+ 		r_thread->pauseOutput (false); // we may be recursing downwards into event loops here. Hence we need to make sure, we don't create a deadlock
  		processREvalRequest (static_cast<REvalRequest *> (e->data ()));
  	} else if ((e->type () == R_CALLBACK_REQUEST_EVENT)) {
+ 		r_thread->pauseOutput (false); // see above
  		processRCallbackRequest (static_cast<RCallbackArgs *> (e->data ()));
  	} else if ((e->type () == RSTARTED_EVENT)) {
***************
*** 293,298 ****
  		if (request->call_length >= 2) {
  			QString lib_name = request->call[1];
  			KMessageBox::information (0, i18n ("The R-backend has indicated that in order to carry out the current task it needs the package '%1', which is not currently installed. We'll open the package-management tool, and there you can try to locate and install the needed package.").arg (lib_name), i18n ("Require package '%1'").arg (lib_name));
! 			RKLoadLibsDialog::showInstallPackagesModal (0, request->in_chain);
  			issueCommand (".rk.rkreply <- \"\"", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
  		} else {
--- 297,303 ----
  		if (request->call_length >= 2) {
  			QString lib_name = request->call[1];
+ 			issueCommand (".rk.rkreply <- NULL", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
  			KMessageBox::information (0, i18n ("The R-backend has indicated that in order to carry out the current task it needs the package '%1', which is not currently installed. We'll open the package-management tool, and there you can try to locate and install the needed package.").arg (lib_name), i18n ("Require package '%1'").arg (lib_name));
! 			RKLoadLibsDialog::showInstallPackagesModal (0, request->in_chain, lib_name);
  			issueCommand (".rk.rkreply <- \"\"", RCommand::App | RCommand::Sync, QString::null, 0, 0, request->in_chain);
  		} else {

Index: rthread.cpp
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rthread.cpp,v
retrieving revision 1.40
retrieving revision 1.41
diff -C2 -d -r1.40 -r1.41
*** rthread.cpp	18 Aug 2006 14:37:30 -0000	1.40
--- rthread.cpp	10 Sep 2006 23:01:07 -0000	1.41
***************
*** 44,47 ****
--- 44,48 ----
  	current_output = 0;
  	out_buf_len = 0;
+ 	output_paused = false;
  }
  
***************
*** 146,150 ****
  			runCommandInternal ("sink (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\", append=TRUE, split=TRUE)\n", &error);
  		}
! 	
  		MUTEX_UNLOCK;
  	
--- 147,151 ----
  			runCommandInternal ("sink (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\", append=TRUE, split=TRUE)\n", &error);
  		}
! 
  		MUTEX_UNLOCK;
  	
***************
*** 158,164 ****
  			runCommandInternal (ccommand, &error, ctype & RCommand::User);
  		}
! 	
  		MUTEX_LOCK;
! 		
  		if (error != NoError) {
  			command->status |= RCommand::WasTried | RCommand::Failed;
--- 159,165 ----
  			runCommandInternal (ccommand, &error, ctype & RCommand::User);
  		}
! 
  		MUTEX_LOCK;
! 
  		if (error != NoError) {
  			command->status |= RCommand::WasTried | RCommand::Failed;
***************
*** 201,204 ****
--- 202,212 ----
  }
  
+ void RThread::waitIfOutputPaused () {
+ 	// don't trace
+ 	while (output_paused) {
+ 		msleep (10);
+ 	}
+ }
+ 
  void RThread::handleOutput (char *buf, int buf_length) {
  	RK_TRACE (RBACKEND);
***************
*** 207,210 ****
--- 215,219 ----
  
  	if (!buf_length) return;
+ 	waitIfOutputPaused ();
  
  	MUTEX_LOCK;
***************
*** 268,271 ****
--- 277,281 ----
  
  	if (!call_length) return;
+ 	waitIfOutputPaused ();
  
  	MUTEX_LOCK;

Index: rthread.h
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rthread.h,v
retrieving revision 1.21
retrieving revision 1.22
diff -C2 -d -r1.21 -r1.22
*** rthread.h	3 Nov 2005 19:34:29 -0000	1.21
--- rthread.h	10 Sep 2006 23:01:07 -0000	1.22
***************
*** 91,94 ****
--- 91,98 ----
  /** "Kills" the thread. Actually this just tells the thread that is is about to be terminated. Allows the thread to terminate gracefully */
  	void kill () { killed = true; };
+ /** Pause output by placing it in a delay loop, until unpaused again */
+ 	void pauseOutput (bool paused) { output_paused = paused; };
+ /** the internal counterpart to pauseOutput () */
+ 	void waitIfOutputPaused ();
  
  /** An enum describing whether initialization of the embedded R-process went well, or what errors occurred. */
***************
*** 165,168 ****
--- 169,173 ----
  /** thread is killed. Should exit as soon as possible. @see kill */
  	bool killed;
+ 	bool output_paused;
  };
  





More information about the rkward-tracker mailing list