[rkward-cvs] SF.net SVN: rkward-code:[4712] trunk/rkward/rkward/rbackend

tfry at users.sf.net tfry at users.sf.net
Tue Apr 23 09:58:19 UTC 2013


Revision: 4712
          http://sourceforge.net/p/rkward/code/4712
Author:   tfry
Date:     2013-04-23 09:58:17 +0000 (Tue, 23 Apr 2013)
Log Message:
-----------
Split out event loop support (which will become more complex, soon) into a separate file

Modified Paths:
--------------
    trunk/rkward/rkward/rbackend/CMakeLists.txt
    trunk/rkward/rkward/rbackend/rkrbackend.cpp
    trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp

Added Paths:
-----------
    trunk/rkward/rkward/rbackend/rkreventloop.cpp
    trunk/rkward/rkward/rbackend/rkreventloop.h

Modified: trunk/rkward/rkward/rbackend/CMakeLists.txt
===================================================================
--- trunk/rkward/rkward/rbackend/CMakeLists.txt	2013-04-23 09:13:27 UTC (rev 4711)
+++ trunk/rkward/rkward/rbackend/CMakeLists.txt	2013-04-23 09:58:17 UTC (rev 4712)
@@ -23,6 +23,7 @@
 	rkrsupport.cpp
 	rkstructuregetter.cpp
 	rkrbackendprotocol_backend.cpp
+	rkreventloop.cpp
 )
 
 SET (

Modified: trunk/rkward/rkward/rbackend/rkrbackend.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkrbackend.cpp	2013-04-23 09:13:27 UTC (rev 4711)
+++ trunk/rkward/rkward/rbackend/rkrbackend.cpp	2013-04-23 09:58:17 UTC (rev 4712)
@@ -48,6 +48,7 @@
 #include "rkstructuregetter.h"
 #include "rklocalesupport.h"
 #include "rksignalsupport.h"
+#include "rkreventloop.h"
 #include "../misc/rkcommonfunctions.h"
 
 #include <stdlib.h>
@@ -69,7 +70,6 @@
 
 #include <Rdefines.h>
 #include <R_ext/Rdynload.h>
-#include <R_ext/eventloop.h>
 #include <R_ext/Callbacks.h>
 #include <R.h>
 #include <Rversion.h>
@@ -835,52 +835,6 @@
 	RK_TRACE (RBACKEND);
 }
 
-#if 0
-static int timeout_counter = 0;
-#endif
-
-void processX11EventsWorker (void *) {
-// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
-#ifndef Q_WS_WIN
-	for (;;) {
-		fd_set *what;
-		what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1, RK_doIntr);
-		R_runHandlers(R_InputHandlers, what);
-		if (what == NULL) break;
-	}
-	/* This seems to be needed to make Rcmdr react to events. Has this always been the case? It was commented out for a long time, without anybody noticing. */
-	R_PolledEvents ();
-#else
-#warning TODO: correct?
-	R_ProcessEvents();
-#endif
-
-#if 0
-// TODO: The remainder of this function had been commented out since R 2.3.x and is not in Rstd_ReadConsole. Do we still need this?
-	/* I don't really understand what I'm doing here, but apparently this is necessary for Tcl-Tk windows to function properly. */
-	R_PolledEvents ();
-	
-/* Maybe we also need to also call R_timeout_handler once in a while? Obviously this is extremely crude code! 
-TODO: verify we really need this. */
-	if (++timeout_counter > 100) {
-//		extern void (* R_timeout_handler) ();	// already defined in Rinferface.h
-		if (R_timeout_handler) R_timeout_handler ();
-		timeout_counter = 0;
-	}
-#endif
-}
-
-void RKRBackend::processX11Events () {
-	// do not trace
-	if (!this_pointer->r_running) return;
-	if (this_pointer->isKilled ()) return;
-
-	RKRBackend::repl_status.eval_depth++;
-// In case an error (or user interrupt) is caught inside processX11EventsWorker, we don't want to long-jump out.
-	R_ToplevelExec (processX11EventsWorker, 0);
-	RKRBackend::repl_status.eval_depth--;
-}
-
 LibExtern int R_interrupts_pending;
 SEXP doError (SEXP call) {
 	RK_TRACE (RBACKEND);
@@ -1001,7 +955,6 @@
 SEXP RKStartGraphicsDevice (SEXP width, SEXP height, SEXP pointsize, SEXP family, SEXP bg, SEXP title, SEXP antialias);
 SEXP RKD_AdjustSize (SEXP devnum);
 void doPendingPriorityCommands ();
-void (* old_R_PolledEvents)(void);
 
 bool RKRBackend::startR () {
 	RK_TRACE (RBACKEND);
@@ -1085,8 +1038,7 @@
 
 	connectCallbacks();
 	RKInsertToplevelStatementFinishedCallback (0);
-	old_R_PolledEvents = R_PolledEvents;
-	R_PolledEvents = doPendingPriorityCommands;
+	RKREventLoop::setEventHandler (doPendingPriorityCommands);
 	default_global_context = R_GlobalContext;
 
 	// get info on R runtime version
@@ -1361,7 +1313,6 @@
 		req.command = command;
 		RKRBackend::this_pointer->handleRequest (&req);
 	}
-	if (old_R_PolledEvents) old_R_PolledEvents ();
 }
 
 // On Windows, using runDirectCommand (".rk.cat.output ...") is not safe during some places where we call this, e.g. in RBusy.
@@ -1472,7 +1423,7 @@
 	while (!request->done) {
 		if (killed) return 0;
 		// NOTE: processX11Events() may, conceivably, lead to new requests, which may also wait for sub-commands!
-		processX11Events ();
+		RKREventLoop::processX11Events ();
 		// NOTE: sleeping and waking up again can be surprisingly CPU-intensive (yes: more than the event processing, above. I have profiled it).
 		// However, we really don't want to introduce too much delay, either.
 		// Thus, the logic is this: If there was no reply within 2 seconds, then probably we're waiting for a user event, and can afford some more
@@ -1480,7 +1431,7 @@
 		if (!request->done) RKRBackendProtocolBackend::msleep (++i < 200 ? 10 : 50);
 	}
 
-	while (pending_priority_command) processX11Events ();  // Probably not needed, but make sure to process priority commands first at all times.
+	while (pending_priority_command) RKREventLoop::processX11Events ();  // Probably not needed, but make sure to process priority commands first at all times.
 
 	RCommandProxy* command = request->takeCommand ();
 	if (!command) return 0;

Added: trunk/rkward/rkward/rbackend/rkreventloop.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkreventloop.cpp	                        (rev 0)
+++ trunk/rkward/rkward/rbackend/rkreventloop.cpp	2013-04-23 09:58:17 UTC (rev 4712)
@@ -0,0 +1,85 @@
+/***************************************************************************
+                          rkreventloop  -  description
+                             -------------------
+    begin                : Tue Apr 23 2013
+    copyright            : (C) 2013 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#include "rkreventloop.h"
+
+#include <R_ext/eventloop.h>
+#include <Rinternals.h>
+
+#include "rkrbackend.h"
+
+#include "../debug.h"
+
+extern "C" void RK_doIntr ();
+
+void processX11EventsWorker (void *) {
+// this basically copied from R's unix/sys-std.c (Rstd_ReadConsole)
+#ifndef Q_WS_WIN
+	for (;;) {
+		fd_set *what;
+		what = R_checkActivityEx(R_wait_usec > 0 ? R_wait_usec : 50, 1, RK_doIntr);
+		R_runHandlers(R_InputHandlers, what);
+		if (what == NULL) break;
+	}
+	/* This seems to be needed to make Rcmdr react to events. Has this always been the case? It was commented out for a long time, without anybody noticing. */
+	R_PolledEvents ();
+#else
+#warning TODO: correct?
+	R_ProcessEvents();
+#endif
+
+#if 0
+// TODO: The remainder of this function had been commented out since R 2.3.x and is not in Rstd_ReadConsole. Do we still need this?
+	/* I don't really understand what I'm doing here, but apparently this is necessary for Tcl-Tk windows to function properly. */
+	R_PolledEvents ();
+	
+/* Maybe we also need to also call R_timeout_handler once in a while? Obviously this is extremely crude code! 
+TODO: verify we really need this. */
+	if (++timeout_counter > 100) {
+//		extern void (* R_timeout_handler) ();	// already defined in Rinferface.h
+		if (R_timeout_handler) R_timeout_handler ();
+		timeout_counter = 0;
+	}
+#endif
+}
+
+void RKREventLoop::processX11Events() {
+	// do not trace
+	if (!RKRBackend::this_pointer->r_running) return;
+	if (RKRBackend::this_pointer->isKilled ()) return;
+
+	RKRBackend::RKRBackend::repl_status.eval_depth++;
+// In case an error (or user interrupt) is caught inside processX11EventsWorker, we don't want to long-jump out.
+	R_ToplevelExec (processX11EventsWorker, 0);
+	RKRBackend::RKRBackend::repl_status.eval_depth--;
+}
+
+void (* RK_old_R_PolledEvents)();
+void (* RK_eventHandlerFunction)() = 0;
+
+void RK_eventHandlerChain () {
+	if (RK_eventHandlerFunction) RK_eventHandlerFunction ();
+	if (RK_old_R_PolledEvents) RK_old_R_PolledEvents ();
+}
+
+void RKREventLoop::setEventHandler (void (* handler) ()) {
+	RK_ASSERT (!RK_eventHandlerFunction);
+
+	RK_old_R_PolledEvents = R_PolledEvents;
+	RK_eventHandlerFunction = handler;
+	R_PolledEvents = RK_eventHandlerChain;
+}

Added: trunk/rkward/rkward/rbackend/rkreventloop.h
===================================================================
--- trunk/rkward/rkward/rbackend/rkreventloop.h	                        (rev 0)
+++ trunk/rkward/rkward/rbackend/rkreventloop.h	2013-04-23 09:58:17 UTC (rev 4712)
@@ -0,0 +1,26 @@
+/***************************************************************************
+                          rkreventloop  -  description
+                             -------------------
+    begin                : Tue Apr 23 2013
+    copyright            : (C) 2013 by Thomas Friedrichsmeier
+    email                : tfry at users.sourceforge.net
+ ***************************************************************************/
+
+/***************************************************************************
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ ***************************************************************************/
+
+#ifndef RKREVENTLOOP_H
+#define RKREVENTLOOP_H
+
+namespace RKREventLoop {
+	void processX11Events ();
+	void setEventHandler (void (* handler) ());
+};
+
+#endif

Modified: trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp
===================================================================
--- trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp	2013-04-23 09:13:27 UTC (rev 4711)
+++ trunk/rkward/rkward/rbackend/rkwarddevice/rkgraphicsdevice_stubs.cpp	2013-04-23 09:58:17 UTC (rev 4712)
@@ -22,6 +22,7 @@
 #include "rkgraphicsdevice_protocol_shared.h"
 #include "rkgraphicsdevice_backendtransmitter.h"
 #include "../rkrbackend.h"
+#include "../rkreventloop.h"
 
 extern "C" {
 #include <R_ext/GraphicsEngine.h>
@@ -51,10 +52,10 @@
 					checkHandleError ();
 				}
 #warning TODO: Use R_CheckUserInterrupt(), instead?
-				if (connection->bytesToWrite ()) RKRBackend::processX11Events ();
+				if (connection->bytesToWrite ()) RKREventLoop::processX11Events ();
 			}
 			while (!RKGraphicsDeviceBackendTransmitter::streamer.readInBuffer ()) {
-				RKRBackend::processX11Events ();
+				RKREventLoop::processX11Events ();
 				if (!connection->waitForReadyRead (10)) {
 					if (checkHandleInterrupt (connection)) {
 						if (have_lock) RKGraphicsDeviceBackendTransmitter::mutex.unlock ();





More information about the rkward-tracker mailing list