[rkward-cvs] SF.net SVN: rkward:[3179] branches/2010_10_18_backend_restructuring_branch/ rkward
tfry at users.sourceforge.net
tfry at users.sourceforge.net
Sat Nov 6 20:26:21 UTC 2010
Revision: 3179
http://rkward.svn.sourceforge.net/rkward/?rev=3179&view=rev
Author: tfry
Date: 2010-11-06 20:26:20 +0000 (Sat, 06 Nov 2010)
Log Message:
-----------
Insert an abstraction layer between frontend and backend. Now I can finally start working on separting the two into different processes.
Also rename RThread to RKRBackend, since it is no longer (necessarily) a QThread.
Modified Paths:
--------------
branches/2010_10_18_backend_restructuring_branch/rkward/agents/showedittextfileagent.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt
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/rinterface.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrsupport.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkstructuregetter.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rkward.cpp
Added Paths:
-----------
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol.h
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp
branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/agents/showedittextfileagent.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/agents/showedittextfileagent.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/agents/showedittextfileagent.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -28,7 +28,7 @@
#include "../windows/rkcommandeditorwindow.h"
#include "../rbackend/rinterface.h"
-#include "../rbackend/rembedinternal.h"
+#include "../rbackend/rkrbackendprotocol.h"
#include "../windows/rkworkplace.h"
#include "../rkglobals.h"
#include "../rkward.h"
@@ -67,7 +67,7 @@
ShowEditTextFileAgent::~ShowEditTextFileAgent () {
RK_TRACE (APP);
- request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (request);
dialog->deleteLater ();
}
@@ -103,7 +103,7 @@
KMessageBox::informationList (RKWardMainWindow::getMain (), i18n ("A command running in the R-engine wants you to see the following file(s):\n"), display_titles, i18n ("Showing file(s)"), "show_files");
delete_files = request->params["delete"].toBool ();
- request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (request);
} else if (request->type == RBackendRequest::EditFiles) {
new ShowEditTextFileAgent (request, i18n ("A command running in the R-engine wants you to edit one or more file(s). Please look at these files, edit them as appriopriate, and save them. When done, press the \"Done\"-button, or close this dialog to resume.\n\n") + display_titles.join ("\n"), i18n ("Edit file(s)"));
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/CMakeLists.txt 2010-11-06 20:26:20 UTC (rev 3179)
@@ -24,6 +24,8 @@
rklocalesupport.cpp
rkrsupport.cpp
rkstructuregetter.cpp
+ rkrbackendprotocol_backend.cpp
+ rkrbackendprotocol_frontend.cpp
)
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rcommand.h 2010-11-06 20:26:20 UTC (rev 3179)
@@ -216,7 +216,7 @@
/** update the given RCommand with the status / data of the proxy command. */
void mergeAndDelete (RCommand *to);
protected:
-friend class RThread;
+friend class RKRBackend;
RCommandProxy (const QString &command, int type);
public: // all these are public for technical reasons, only.
QString command;
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -18,12 +18,13 @@
#include "rembedinternal.h"
// static
-RThread *RThread::this_pointer = 0;
-RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0, false, false };
-void* RThread::default_global_context = 0;
+RKRBackend *RKRBackend::this_pointer = 0;
+RKRBackend::RKReplStatus RKRBackend::repl_status = { QByteArray (), 0, true, 0, 0, RKRBackend::RKReplStatus::NoUserCommand, 0, false, false };
+void* RKRBackend::default_global_context = 0;
#include <qstring.h>
#include <QStringList>
+#include <QThread>
#include <qtextcodec.h>
#include <klocale.h>
@@ -32,7 +33,6 @@
#include "rkrsupport.h"
#include "rkstructuregetter.h"
-#include "rinterface.h"
#include "rklocalesupport.h"
#include "rkpthreadsupport.h"
#include "rksignalsupport.h"
@@ -86,16 +86,20 @@
#endif
void RK_scheduleIntr () {
- RThread::repl_status.interrupted = true;
+ RKRBackend::repl_status.interrupted = true;
RKSignalSupport::callOldSigIntHandler ();
}
void RK_doIntr () {
RK_scheduleIntr ();
- RThread::repl_status.interrupted = true;
+ RKRBackend::repl_status.interrupted = true;
R_CheckUserInterrupt ();
}
+void RKRBackend::scheduleInterrupt () {
+ RK_scheduleIntr ();
+}
+
// some functions we need that are not declared
extern void Rf_PrintWarnings (void);
extern void run_Rmainloop (void);
@@ -107,8 +111,8 @@
#include "rdata.h"
extern SEXP RKWard_RData_Tag;
-SEXP parseCommand (const QString &command_qstring, RThread::RKWardRError *error);
-SEXP runCommandInternalBase (SEXP pr, RThread::RKWardRError *error);
+SEXP parseCommand (const QString &command_qstring, RKRBackend::RKWardRError *error);
+SEXP runCommandInternalBase (SEXP pr, RKRBackend::RKWardRError *error);
// ############## R Standard callback overrides BEGIN ####################
Rboolean RKToplevelStatementFinishedCallback (SEXP expr, SEXP value, Rboolean succeeded, Rboolean visible, void *) {
@@ -117,17 +121,17 @@
Q_UNUSED (value);
Q_UNUSED (visible);
- if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context)) { // Yes, toplevel-handlers _do_ get called in a browser context!
- RK_ASSERT (RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandRunning);
+ if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.in_browser_context)) { // Yes, toplevel-handlers _do_ get called in a browser context!
+ RK_ASSERT (RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandRunning);
if (succeeded) {
- 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;
- RThread::this_pointer->commandFinished ();
- } else RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandTransmitted;
+ RKRBackend::repl_status.user_command_successful_up_to = RKRBackend::repl_status.user_command_parsed_up_to;
+ if (RKRBackend::repl_status.user_command_completely_transmitted) {
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
+ RKRBackend::this_pointer->commandFinished ();
+ } else RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandTransmitted;
} else {
// well, this point of code is never reached with R up to 2.12.0. Instead failed user commands are handled in doError().
- RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandFailed;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandFailed;
}
}
@@ -137,7 +141,7 @@
void RKInsertToplevelStatementFinishedCallback (void *) {
RK_TRACE (RBACKEND);
- if (RThread::this_pointer->r_running) {
+ if (RKRBackend::this_pointer->r_running) {
int pos;
Rf_addTaskCallback (&RKToplevelStatementFinishedCallback, 0, &RKInsertToplevelStatementFinishedCallback, "_rkward_main_callback", &pos);
}
@@ -146,9 +150,9 @@
void RKTransmitNextUserCommandChunk (unsigned char* buf, int buflen) {
RK_TRACE (RBACKEND);
- RK_ASSERT (RThread::repl_status.user_command_transmitted_up_to <= RThread::repl_status.user_command_buffer.length ()); // NOTE: QByteArray::length () does not count the trailing '\0'
- const char* current_buffer = RThread::repl_status.user_command_buffer.data ();
- current_buffer += RThread::repl_status.user_command_transmitted_up_to; // Skip what we have already transmitted
+ RK_ASSERT (RKRBackend::repl_status.user_command_transmitted_up_to <= RKRBackend::repl_status.user_command_buffer.length ()); // NOTE: QByteArray::length () does not count the trailing '\0'
+ const char* current_buffer = RKRBackend::repl_status.user_command_buffer.data ();
+ current_buffer += RKRBackend::repl_status.user_command_transmitted_up_to; // Skip what we have already transmitted
bool reached_eof = false;
int pos = 0;
@@ -163,10 +167,10 @@
++current_buffer;
++pos;
}
- RThread::repl_status.user_command_transmitted_up_to += (pos + 1);
+ RKRBackend::repl_status.user_command_transmitted_up_to += (pos + 1);
if (reached_eof) {
buf[pos] = '\n';
- RThread::repl_status.user_command_completely_transmitted = true;
+ RKRBackend::repl_status.user_command_completely_transmitted = true;
}
buf[++pos] = '\0';
}
@@ -175,26 +179,26 @@
RK_TRACE (RBACKEND);
RK_ASSERT (buf && buflen);
- RK_ASSERT (RThread::repl_status.eval_depth >= 0);
+ RK_ASSERT (RKRBackend::repl_status.eval_depth >= 0);
- if (RThread::repl_status.in_browser_context) { // previously we were in a browser context. Check, whether we've left that.
- if (RThread::default_global_context == R_GlobalContext) {
- RThread::repl_status.in_browser_context = false;
+ if (RKRBackend::repl_status.in_browser_context) { // previously we were in a browser context. Check, whether we've left that.
+ if (RKRBackend::default_global_context == R_GlobalContext) {
+ RKRBackend::repl_status.in_browser_context = false;
RK_ASSERT (!hist);
}
}
- if ((!RThread::repl_status.in_browser_context) && (RThread::repl_status.eval_depth == 0)) {
+ if ((!RKRBackend::repl_status.in_browser_context) && (RKRBackend::repl_status.eval_depth == 0)) {
while (1) {
- if (RThread::repl_status.user_command_status == RThread::RKReplStatus::NoUserCommand) {
- RCommandProxy *command = RThread::this_pointer->fetchNextCommand ();
+ if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::NoUserCommand) {
+ RCommandProxy *command = RKRBackend::this_pointer->fetchNextCommand ();
if (!command) {
return 0; // jumps out of the event loop!
}
if (!(command->type & RCommand::User)) {
- RThread::this_pointer->runCommand (command);
- RThread::this_pointer->commandFinished ();
+ RKRBackend::this_pointer->runCommand (command);
+ RKRBackend::this_pointer->commandFinished ();
} else {
// so, we are about to transmit a new user command, which is quite a complex endeavour...
/* Some words about running user commands:
@@ -206,47 +210,47 @@
- One difficulty lies in finding out, just when a command has finished (successfully or with an error). RKToplevelStatementFinishCallback(), and doError() handle the respective cases.
NOTE; in R 2.12.0 and above, Rf_countContexts() might help to find out when we are back to square 1!
*/
- 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);
+ RKRBackend::repl_status.user_command_transmitted_up_to = 0;
+ RKRBackend::repl_status.user_command_completely_transmitted = false;
+ RKRBackend::repl_status.user_command_parsed_up_to = 0;
+ RKRBackend::repl_status.user_command_successful_up_to = 0;
+ RKRBackend::repl_status.user_command_buffer = RKRBackend::this_pointer->current_locale_codec->fromUnicode (command->command);
RKTransmitNextUserCommandChunk (buf, buflen);
- RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandTransmitted;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandTransmitted;
return 1;
}
- } else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandTransmitted) {
- if (RThread::repl_status.user_command_completely_transmitted) {
+ } else if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandTransmitted) {
+ if (RKRBackend::repl_status.user_command_completely_transmitted) {
// fully transmitted, but R is still asking for more? This looks like an incomplete statement.
// HOWEVER: It may also have been an empty statement such as " ", so let's check whether the prompt looks like a "continue" prompt
bool incomplete = false;
- if (RThread::this_pointer->current_locale_codec->toUnicode (prompt) == RKRSupport::SEXPToString (Rf_GetOption (Rf_install ("continue"), R_BaseEnv))) {
+ if (RKRBackend::this_pointer->current_locale_codec->toUnicode (prompt) == RKRSupport::SEXPToString (Rf_GetOption (Rf_install ("continue"), R_BaseEnv))) {
incomplete = true;
}
- if (incomplete) RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorIncomplete;
- RThread::repl_status.user_command_status = RThread::RKReplStatus::ReplIterationKilled;
+ if (incomplete) RKRBackend::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorIncomplete;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::ReplIterationKilled;
#warning TODO: use Rf_error(""), instead?
RK_doIntr (); // to discard the buffer
} else {
RKTransmitNextUserCommandChunk (buf, buflen);
return 1;
}
- } else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandSyntaxError) {
- RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorSyntax;
- RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
- RThread::this_pointer->commandFinished ();
- } else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandRunning) {
+ } else if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandSyntaxError) {
+ RKRBackend::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorSyntax;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
+ RKRBackend::this_pointer->commandFinished ();
+ } else if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandRunning) {
// This can mean three different things:
// 1) User called readline ()
// 2) User called browser ()
// 3) R jumped us back to toplevel behind our backs.
// Let's find out, which one it is.
- if (hist && (RThread::default_global_context != R_GlobalContext)) {
+ if (hist && (RKRBackend::default_global_context != R_GlobalContext)) {
break; // this looks like a call to browser(). Will be handled below.
}
int n_frames = 0;
- RCommandProxy *dummy = RThread::this_pointer->runDirectCommand ("sys.nframe()", RCommand::GetIntVector);
+ RCommandProxy *dummy = RKRBackend::this_pointer->runDirectCommand ("sys.nframe()", RCommand::GetIntVector);
if ((dummy->getDataType () == RData::IntVector) && (dummy->getDataLength () == 1)) {
n_frames = dummy->getIntVector ()[0];
}
@@ -255,46 +259,46 @@
if (n_frames < 1) {
// No active frames? This can't be a call to readline(), then, so probably R jumped us back to toplevel, behind our backs.
// For safety, let's reset and start over.
- RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
- RThread::repl_status.user_command_status = RThread::RKReplStatus::ReplIterationKilled;
+ RKRBackend::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::ReplIterationKilled;
RK_doIntr (); // to discard the buffer
} else {
// A call to readline(). Will be handled below
break;
}
- } else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandFailed) {
- RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
- RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
- RThread::this_pointer->commandFinished ();
+ } else if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandFailed) {
+ RKRBackend::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
+ RKRBackend::this_pointer->commandFinished ();
} else {
- RK_ASSERT (RThread::repl_status.user_command_status == RThread::RKReplStatus::ReplIterationKilled);
- RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
- RThread::this_pointer->commandFinished ();
+ RK_ASSERT (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::ReplIterationKilled);
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::NoUserCommand;
+ RKRBackend::this_pointer->commandFinished ();
}
}
}
// here, we handle readline() calls and such, i.e. not the regular prompt for code
// browser() also takes us here.
- if (hist && (RThread::default_global_context != R_GlobalContext)) {
+ if (hist && (RKRBackend::default_global_context != R_GlobalContext)) {
// TODO: give browser() special handling!
- RThread::repl_status.in_browser_context = true;
+ RKRBackend::repl_status.in_browser_context = true;
}
RBackendRequest request (true, RBackendRequest::ReadLine);
request.params["prompt"] = QVariant (prompt);
request.params["cancelled"] = QVariant (false);
- RThread::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->handleRequest (&request);
if (request.params["cancelled"].toBool ()) {
- if (RThread::this_pointer->current_command) RThread::this_pointer->current_command->status |= RCommand::Canceled;
+ if (RKRBackend::this_pointer->current_command) RKRBackend::this_pointer->current_command->status |= RCommand::Canceled;
RK_doIntr();
// threoretically, the above should have got us out of the loop, but for good measure:
Rf_error ("cancelled");
RK_ASSERT (false); // should not reach this point.
}
- QByteArray localres = RThread::this_pointer->current_locale_codec->fromUnicode (request.params["result"].toString ());
+ QByteArray localres = RKRBackend::this_pointer->current_locale_codec->fromUnicode (request.params["result"].toString ());
// need to append a newline, here. TODO: theoretically, RReadConsole comes back for more, if \0 was encountered before \n.
qstrncpy ((char *) buf, localres.left (buflen - 2).append ('\n').data (), buflen);
return 1;
@@ -310,22 +314,22 @@
RK_TRACE (RBACKEND);
// output while nothing else is running (including handlers?) -> This may be a syntax error.
- if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->isKilled ())) {
- if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandTransmitted) {
+ if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.in_browser_context) && (!RKRBackend::this_pointer->isKilled ())) {
+ if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandTransmitted) {
// status UserCommandTransmitted might have been set from RKToplevelStatementFinishedHandler, too, in which case all is fine
// (we're probably inside another task handler at this point, then)
- if (RThread::repl_status.user_command_parsed_up_to < RThread::repl_status.user_command_transmitted_up_to) {
- RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandSyntaxError;
+ if (RKRBackend::repl_status.user_command_parsed_up_to < RKRBackend::repl_status.user_command_transmitted_up_to) {
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandSyntaxError;
}
- } else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::ReplIterationKilled) {
+ } else if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::ReplIterationKilled) {
// purge superflous newlines
if (QString ("\n") == buf) return;
} else {
- RK_ASSERT (RThread::repl_status.user_command_status != RThread::RKReplStatus::NoUserCommand);
+ RK_ASSERT (RKRBackend::repl_status.user_command_status != RKRBackend::RKReplStatus::NoUserCommand);
}
}
- RThread::this_pointer->handleOutput (RThread::this_pointer->current_locale_codec->toUnicode (buf, buflen), buflen, type == 0 ? ROutput::Output : ROutput::Warning);
+ RKRBackend::this_pointer->handleOutput (RKRBackend::this_pointer->current_locale_codec->toUnicode (buf, buflen), buflen, type == 0 ? ROutput::Output : ROutput::Warning);
}
/** For R callbacks that we want to disable, entirely */
@@ -336,19 +340,19 @@
void RCleanUp (SA_TYPE saveact, int status, int RunLast) {
RK_TRACE (RBACKEND);
- if (RThread::this_pointer->killed == RThread::AlreadyDead) return; // Nothing to clean up
+ if (RKRBackend::this_pointer->killed == RKRBackend::AlreadyDead) return; // Nothing to clean up
// we could be in a signal handler, and the stack base may have changed.
uintptr_t old_lim = R_CStackLimit;
R_CStackLimit = (uintptr_t)-1;
- if ((status != 0) && (RThread::this_pointer->killed != RThread::ExitNow)) RThread::this_pointer->killed = RThread::EmergencySaveThenExit;
+ if ((status != 0) && (RKRBackend::this_pointer->killed != RKRBackend::ExitNow)) RKRBackend::this_pointer->killed = RKRBackend::EmergencySaveThenExit;
if (saveact != SA_SUICIDE) {
- if (!RThread::this_pointer->isKilled ()) {
+ if (!RKRBackend::this_pointer->isKilled ()) {
RBackendRequest request (true, RBackendRequest::BackendExit);
request.params["message"] = QVariant (i18n ("The R engine has shut down with status: %1").arg (status));
- RThread::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->handleRequest (&request);
}
if (RunLast) R_dot_Last ();
@@ -357,13 +361,13 @@
R_CleanTempDir ();
}
- RThread::this_pointer->r_running = false; // To signify we have finished everything else and are now trying to create an emergency save (if applicable)
+ RKRBackend::this_pointer->r_running = false; // To signify we have finished everything else and are now trying to create an emergency save (if applicable)
- if (RThread::this_pointer->killed == RThread::EmergencySaveThenExit) {
+ if (RKRBackend::this_pointer->killed == RKRBackend::EmergencySaveThenExit) {
if (R_DirtyImage) R_SaveGlobalEnvToFile (RKCommonFunctions::getUseableRKWardSavefileName ("rkward_recover", ".RData").toLocal8Bit ());
}
- RThread::this_pointer->killed = RThread::AlreadyDead; // just in case
+ RKRBackend::this_pointer->killed = RKRBackend::AlreadyDead; // just in case
R_CStackLimit = old_lim; // well, it should not matter any longer, but...
}
@@ -371,21 +375,21 @@
void RSuicide (const char* message) {
RK_TRACE (RBACKEND);
- if (!RThread::this_pointer->isKilled ()) {
+ if (!RKRBackend::this_pointer->isKilled ()) {
RBackendRequest request (true, RBackendRequest::BackendExit);
request.params["message"] = QVariant (i18n ("The R engine has encountered a fatal error:\n%1").arg (message));
- RThread::this_pointer->handleRequest (&request);
- RThread::this_pointer->killed = RThread::EmergencySaveThenExit;
+ RKRBackend::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->killed = RKRBackend::EmergencySaveThenExit;
RCleanUp (SA_SUICIDE, 1, 0);
} else {
RK_ASSERT (false);
}
}
-void RThread::tryToDoEmergencySave () {
+void RKRBackend::tryToDoEmergencySave () {
RK_TRACE (RBACKEND);
- if (inRThread ()) {
+ if (RKRBackendProtocolBackend::inRThread ()) {
// If we are in the correct thread, things are easy:
RCleanUp (SA_SUICIDE, 1, 0);
RK_doIntr (); // to jump out of the loop, if needed
@@ -393,15 +397,15 @@
// If we are in the wrong thread, things are a lot more tricky. We need to cause the R thread to exit, and wait for it to finish saving.
// Fortunately, if we are in the wrong thread, that probably means, the R thread did *not* crash, and will thus still be functional
this_pointer->killed = EmergencySaveThenExit;
- this_pointer->interruptProcessing (true);
+ RK_scheduleIntr ();
for (int i = 0; i < 100; ++i) { // give it up to ten seconds to intterrupt and exit the loop
if (!this_pointer->r_running) break;
- msleep (100);
+ RKRBackendProtocolBackend::msleep (100);
}
if (!this_pointer->r_running) {
for (int i = 0; i < 600; ++i) { // give it up to sixty seconds to finish saving
if (this_pointer->killed == AlreadyDead) return; // finished
- msleep (100);
+ RKRBackendProtocolBackend::msleep (100);
}
}
RK_ASSERT (false); // Too bad, but we seem to be stuck. No chance but to return (and crash)
@@ -423,9 +427,9 @@
RBackendRequest request (true, RBackendRequest::ChooseFile);
request.params["new"] = QVariant ((bool) isnew);
- RThread::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->handleRequest (&request);
- QByteArray localres = RThread::this_pointer->current_locale_codec->fromUnicode (request.params["result"].toString ());
+ QByteArray localres = RKRBackend::this_pointer->current_locale_codec->fromUnicode (request.params["result"].toString ());
qstrncpy ((char *) buf, localres.data (), len);
// return length of filename (strlen (buf))
@@ -449,7 +453,7 @@
request.params["titles"] = QVariant (titles);
request.params["wtitle"] = QVariant (wtitle);
- RThread::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->handleRequest (&request);
}
int REditFiles (int nfile, const char **file, const char **title, const char *wtitle) {
@@ -516,7 +520,7 @@
request.params["button_no"] = QVariant (button_no);
request.params["button_cancel"] = QVariant (button_cancel);
- RThread::this_pointer->handleRequest (&request);
+ RKRBackend::this_pointer->handleRequest (&request);
if (wait) {
QString ret = request.params["result"].toString ();
@@ -554,18 +558,18 @@
// 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;
+ if (RKRBackend::repl_status.user_command_status == RKRBackend::RKReplStatus::UserCommandTransmitted) {
+ RKRBackend::repl_status.user_command_parsed_up_to = RKRBackend::repl_status.user_command_transmitted_up_to;
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandRunning;
}
}
}
// ############## R Standard callback overrides END ####################
-char *RThread::na_char_internal = new char;
+char *RKRBackend::na_char_internal = new char;
-RThread::RThread () {
+RKRBackend::RKRBackend () {
RK_TRACE (RBACKEND);
current_locale_codec = QTextCodec::codecForLocale ();
@@ -576,11 +580,6 @@
RK_ASSERT (this_pointer == 0);
this_pointer = this;
out_buf_len = 0;
-
-#ifdef Q_WS_WIN
- // we hope that on other platforms the default is reasonable
- setStackSize (0xa00000); // 10MB as recommended by r_exts-manual
-#endif
}
#ifdef Q_WS_WIN
@@ -614,11 +613,11 @@
R_SetParams(&RK_R_Params);
}
#else
-void RThread::setupCallbacks () {
+void RKRBackend::setupCallbacks () {
RK_TRACE (RBACKEND);
}
-void RThread::connectCallbacks () {
+void RKRBackend::connectCallbacks () {
RK_TRACE (RBACKEND);
// IMPORTANT: see also the #ifdef QS_WS_WIN-portion!
@@ -647,7 +646,7 @@
}
#endif
-RThread::~RThread () {
+RKRBackend::~RKRBackend () {
RK_TRACE (RBACKEND);
}
@@ -686,35 +685,35 @@
#endif
}
-void RThread::processX11Events () {
+void RKRBackend::processX11Events () {
// do not trace
if (!this_pointer->r_running) return;
if (this_pointer->isKilled ()) return;
- RThread::repl_status.eval_depth++;
+ 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);
- RThread::repl_status.eval_depth--;
+ RKRBackend::repl_status.eval_depth--;
}
extern int R_interrupts_pending;
SEXP doError (SEXP call) {
RK_TRACE (RBACKEND);
- if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context) && (!RThread::this_pointer->isKilled ())) {
- RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandFailed;
+ if ((RKRBackend::repl_status.eval_depth == 0) && (!RKRBackend::repl_status.in_browser_context) && (!RKRBackend::this_pointer->isKilled ())) {
+ RKRBackend::repl_status.user_command_status = RKRBackend::RKReplStatus::UserCommandFailed;
}
- if (RThread::repl_status.interrupted) {
+ if (RKRBackend::repl_status.interrupted) {
// it is unlikely, but possible, that an interrupt signal was received, but the current command failed for some other reason, before processing was acutally interrupted. In this case, R_interrupts_pending if not yet cleared.
// NOTE: if R_interrupts_pending stops being exported one day, we might be able to use R_CheckUserInterrupt() inside an R_ToplevelExec() to find out, whether an interrupt was still pending.
if (!R_interrupts_pending) {
- RThread::repl_status.interrupted = false;
- foreach (RCommandProxy *command, RThread::this_pointer->all_current_commands) command->status |= RCommand::Canceled;
+ RKRBackend::repl_status.interrupted = false;
+ foreach (RCommandProxy *command, RKRBackend::this_pointer->all_current_commands) command->status |= RCommand::Canceled;
RK_DO (qDebug ("interrupted"), RBACKEND, DL_DEBUG);
}
} else {
QString string = RKRSupport::SEXPToString (call);
- RThread::this_pointer->handleOutput (string, string.length (), ROutput::Error);
+ RKRBackend::this_pointer->handleOutput (string, string.length (), ROutput::Error);
RK_DO (qDebug ("error '%s'", qPrintable (string)), RBACKEND, DL_DEBUG);
}
return R_NilValue;
@@ -729,15 +728,15 @@
if (list.count () == 2) { // schedule symbol update for later
if (list[0] == "ws") {
// always keep in mind: No current command can happen for tcl/tk events.
- if ((!RThread::this_pointer->current_command) || (RThread::this_pointer->current_command->type & RCommand::ObjectListUpdate) || (!(RThread::this_pointer->current_command->type & RCommand::Sync))) { // ignore Sync commands that are not flagged as ObjectListUpdate
- if (!RThread::this_pointer->changed_symbol_names.contains (list[1])) RThread::this_pointer->changed_symbol_names.append (list[1]);
+ if ((!RKRBackend::this_pointer->current_command) || (RKRBackend::this_pointer->current_command->type & RCommand::ObjectListUpdate) || (!(RKRBackend::this_pointer->current_command->type & RCommand::Sync))) { // ignore Sync commands that are not flagged as ObjectListUpdate
+ if (!RKRBackend::this_pointer->changed_symbol_names.contains (list[1])) RKRBackend::this_pointer->changed_symbol_names.append (list[1]);
}
return R_NilValue;
}
}
#warning TODO: extend this by sychronity parameter
- RThread::this_pointer->handleHistoricalSubstackRequest (list);
+ RKRBackend::this_pointer->handleHistoricalSubstackRequest (list);
return R_NilValue;
}
@@ -750,8 +749,8 @@
RK_TRACE (RBACKEND);
RK_DO (qDebug ("Changing locale"), RBACKEND, DL_WARNING);
- RThread::this_pointer->current_locale_codec = RKGetCurrentLocaleCodec ();
- RK_DO (qDebug ("New locale codec is %s", RThread::this_pointer->current_locale_codec->name ().data ()), RBACKEND, DL_WARNING);
+ RKRBackend::this_pointer->current_locale_codec = RKGetCurrentLocaleCodec ();
+ RK_DO (qDebug ("New locale codec is %s", RKRBackend::this_pointer->current_locale_codec->name ().data ()), RBACKEND, DL_WARNING);
return R_NilValue;
}
@@ -760,10 +759,10 @@
SEXP doLocaleName () {
RK_TRACE (RBACKEND);
- RK_ASSERT (RThread::this_pointer->current_locale_codec);
+ RK_ASSERT (RKRBackend::this_pointer->current_locale_codec);
SEXP res = Rf_allocVector(STRSXP, 1);
PROTECT (res);
- SET_STRING_ELT (res, 0, Rf_mkChar (RThread::this_pointer->current_locale_codec->name ().data ()));
+ SET_STRING_ELT (res, 0, Rf_mkChar (RKRBackend::this_pointer->current_locale_codec->name ().data ()));
UNPROTECT (1);
return res;
}
@@ -793,7 +792,7 @@
return (R_NilValue);
}
-bool RThread::startR () {
+bool RKRBackend::startR () {
RK_TRACE (RBACKEND);
setupCallbacks ();
@@ -882,20 +881,20 @@
return true;
}
-void RThread::enterEventLoop () {
+void RKRBackend::enterEventLoop () {
RK_TRACE (RBACKEND);
run_Rmainloop ();
// NOTE: Do NOT run Rf_endEmbeddedR(). It does more that we want. We rely on RCleanup, instead.
}
-SEXP parseCommand (const QString &command_qstring, RThread::RKWardRError *error) {
+SEXP parseCommand (const QString &command_qstring, RKRBackend::RKWardRError *error) {
RK_TRACE (RBACKEND);
ParseStatus status = PARSE_NULL;
SEXP cv, pr;
- QByteArray localc = RThread::this_pointer->current_locale_codec->fromUnicode (command_qstring); // needed so the string below does not go out of scope
+ QByteArray localc = RKRBackend::this_pointer->current_locale_codec->fromUnicode (command_qstring); // needed so the string below does not go out of scope
const char *command = localc.data ();
PROTECT(cv=Rf_allocVector(STRSXP, 1));
@@ -915,13 +914,13 @@
if (status != PARSE_OK) {
if ((status == PARSE_INCOMPLETE) || (status == PARSE_EOF)) {
- *error = RThread::Incomplete;
+ *error = RKRBackend::Incomplete;
} else if (status == PARSE_ERROR) {
//extern SEXP parseError (SEXP call, int linenum);
//parseError (R_NilValue, 0);
- *error = RThread::SyntaxError;
+ *error = RKRBackend::SyntaxError;
} else { // PARSE_NULL
- *error = RThread::OtherError;
+ *error = RKRBackend::OtherError;
}
pr = R_NilValue;
}
@@ -929,7 +928,7 @@
return pr;
}
-SEXP runCommandInternalBase (SEXP pr, RThread::RKWardRError *error) {
+SEXP runCommandInternalBase (SEXP pr, RKRBackend::RKWardRError *error) {
RK_TRACE (RBACKEND);
SEXP exp;
@@ -953,9 +952,9 @@
}
if (r_error) {
- *error = RThread::OtherError;
+ *error = RKRBackend::OtherError;
} else {
- *error = RThread::NoError;
+ *error = RKRBackend::NoError;
}
UNPROTECT(1); /* pr */
@@ -973,7 +972,7 @@
return exp;
}
-bool RThread::runDirectCommand (const QString &command) {
+bool RKRBackend::runDirectCommand (const QString &command) {
RK_TRACE (RBACKEND);
RCommandProxy c (command, RCommand::App | RCommand::Sync | RCommand::Internal);
@@ -981,7 +980,7 @@
return ((c.status & RCommand::WasTried) && !(c.status & RCommand::Failed));
}
-RCommandProxy *RThread::runDirectCommand (const QString &command, RCommand::CommandTypes datatype) {
+RCommandProxy *RKRBackend::runDirectCommand (const QString &command, RCommand::CommandTypes datatype) {
RK_TRACE (RBACKEND);
RK_ASSERT ((datatype >= RCommand::GetIntVector) && (datatype <= RCommand::GetStructuredData));
@@ -990,7 +989,7 @@
return c;
}
-void RThread::runCommand (RCommandProxy *command) {
+void RKRBackend::runCommand (RCommandProxy *command) {
RK_TRACE (RBACKEND);
RK_ASSERT (command);
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h 2010-11-06 20:26:20 UTC (rev 3179)
@@ -22,13 +22,13 @@
#include <QMap>
#include <QVariant>
-#include <QThread>
#include <QMutex>
#include <QStringList>
#include <QEvent>
#include "rcommand.h"
#include "rcommandstack.h"
+#include "rkrbackendprotocol.h"
#ifdef Q_WS_WIN
extern "C" {
@@ -36,74 +36,11 @@
}
#endif
-class RBackendRequest {
-public:
- enum RCallbackType {
- BackendExit,
- ShowMessage,
- ShowFiles,
- ChooseFile,
- EditFiles,
- ReadLine,
- CommandOut,
- Started,
- EvalRequest,
- CallbackRequest,
- HistoricalSubstackRequest,
- OtherRequest /**< Any other type of request. Note: which requests are in the enum, and which are not has mostly historical reasons. @see params */
- };
-
- RBackendRequest (bool synchronous, RCallbackType type) {
- RBackendRequest::synchronous = synchronous;
- RBackendRequest::type = type;
- done = false;
- command = 0;
- }
- ~RBackendRequest () {};
-
- RBackendRequest *duplicate () {
- RBackendRequest* ret = new RBackendRequest (synchronous, type);
- ret->done = done;
- ret->command = command;
- ret->params = params;
- return ret;
- }
-
- void completed () {
- if (!synchronous) delete this;
- else done = true;
- }
-
-/** Should this request be handled synchronously? False by default. */
- bool synchronous;
-/** For synchronous requests, only: The frontend-thread will set this to true (using completed()), once the request has been "completed". Important: The backend thread MUST NOT touch a request after it has been sent, and before "done" has been set to true. */
- bool done;
- RCallbackType type;
-/** For synchronous requests, only: If the the frontend wants any commands to be executed, it will place the next one in this slot. The backend thread should keep executing commands (in a sub-eventloop) while this is non-zero. Also, the backend-thread may place here any command that has just finished. */
- RCommandProxy *command;
-/** Any other parameters, esp. for RCallbackType::OtherRequest. Can be used in both directions. */
- QVariantMap params;
-};
-
class QStringList;
class QTextCodec;
class RInterface;
struct ROutput;
-/** Simple event class to relay information from the RThread to the main thread. This is basically like QCustomEvent in Qt3*/
-class RKRBackendEvent : public QEvent {
-public:
- enum EventType {
- RKWardEvent = QEvent::User + 1
- };
- RKRBackendEvent (RBackendRequest* data=0) : QEvent ((QEvent::Type) RKWardEvent) { _data = data; };
- RKRBackendEvent ();
-
- RBackendRequest* data () { return _data; };
-private:
- RBackendRequest* _data;
-};
-
/** This class represents the thread the R backend is running in. So to speak, this is where the "eventloop" of R is running. The main thing happening
in this class, is that it enters R's REPL (Read-evaluate-parse-loop). Whenever there are commands to be executed, those get evaluated. When there are not,
processing of X11-Events in R is triggered. The rest of the time the thread sleeps.
@@ -120,25 +57,25 @@
This subordinate/nested eventloop is done in handleRequest ().
-A closely related class is RInterface: RThread communicates with RInterface by placing QCustomEvent s, when commands are done
-or when the backend needs information from the frontend. For historical reasons, the definitions of RThread class-members are currently spread over different files.
+A closely related class is RInterface: RKRBackend communicates with RInterface by placing QCustomEvent s, when commands are done
+or when the backend needs information from the frontend. For historical reasons, the definitions of RKRBackend class-members are currently spread over different files.
-Only one RThread-object can be used in an application.
+Only one RKRBackend-object can be used in an application.
Don't use this class in RKWard directly. Unless you really want to modify the internal workings of the backend, you will want to look at RInterface and use the functions there.
@see RInterface
@author Thomas Friedrichsmeier
*/
-class RThread : public QThread {
+class RKRBackend {
public:
-/** constructor. Only one RThread should ever be created, and that happens in RInterface::RInterface (). */
- RThread ();
+/** constructor. Only one RKRBackend should ever be created, and that happens in RInterface::RInterface (). */
+ RKRBackend ();
/** destructor */
- virtual ~RThread ();
+ virtual ~RKRBackend ();
-/** interrupt processing of the current command. This is much like the user pressing Ctrl+C in a terminal with R. This is probably the only non-portable function in RThread, but I can't see a good way around placing it here, or to make it portable. */
- void interruptProcessing (bool interrupt);
+/** interrupt processing of the current command. This is much like the user pressing Ctrl+C in a terminal with R. This is probably the only non-portable function in RKRBackend, but I can't see a good way around placing it here, or to make it portable. */
+ static void interruptProcessing (bool interrupt);
/** Enum specifying types of errors that may occur while parsing/evaluating a command in R */
enum RKWardRError {
@@ -188,7 +125,7 @@
void runCommand (RCommandProxy *command);
/** only one instance of this class may be around. This pointer keeps the reference to it, for interfacing to from C to C++ */
- static RThread *this_pointer;
+ static RKRBackend *this_pointer;
static char *na_char_internal;
static void tryToDoEmergencySave ();
bool r_running;
@@ -197,14 +134,14 @@
return (r_version >= (1000 * major + 10 * minor + revision));
}
-/** thread is killed. Should exit as soon as possible. @see kill */
+/** backend is killed. Should exit as soon as possible. @see kill */
enum KillType {
NotKilled = 0,
ExitNow = 1,
EmergencySaveThenExit = 2,
AlreadyDead = 3
} killed;
-/** "Kills" the thread. Actually this just tells the thread that is is about to be terminated. Allows the thread to terminate gracefully */
+/** "Kills" the backend. Actually this just tells the thread that is is about to be terminated. Allows the thread to terminate gracefully */
void kill () { killed = ExitNow; };
bool isKilled () { return (killed != NotKilled); };
@@ -235,10 +172,10 @@
void commandFinished (bool check_object_updates_needed=true);
/** A list of symbols that have been assigned new values during the current command */
QStringList changed_symbol_names;
- static bool inRThread () { return (currentThread () == this_pointer); };
+/** the main loop. See \ref RKRBackend for a more detailed description */
+ void run ();
+ static void scheduleInterrupt ();
protected:
-/** 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;
/** If the length of the current output buffer is too long, this will pause any further output until the main thread has had a chance to catch up. */
void waitIfOutputBufferExceeded ();
RCommandProxy* handleRequest (RBackendRequest *request, bool mayHandleSubstack);
@@ -249,9 +186,6 @@
void connectCallbacks ();
int r_version;
-protected:
-/** the main loop. See \ref RThread for a more detailed description */
- void run ();
private:
/** A copy of the names of the toplevel environments (as returned by "search ()"). */
QStringList toplevel_env_names;
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -17,8 +17,8 @@
#include "rinterface.h"
-#include "rembedinternal.h"
#include "rcommandstack.h"
+#include "rkrbackendprotocol.h"
#include "../rkward.h"
#include "../settings/rksettingsmoduler.h"
#include "../settings/rksettingsmodulegeneral.h"
@@ -87,6 +87,7 @@
previously_idle = false;
previous_command = 0;
locked = 0;
+ backend_dead = false;
// create a fake init command
RCommand *fake = new RCommand (i18n ("R Startup"), RCommand::App | RCommand::Sync | RCommand::ObjectListUpdate, i18n ("R Startup"), this, STARTUP_PHASE2_COMPLETE);
@@ -96,7 +97,8 @@
connect (flush_timer, SIGNAL (timeout ()), this, SLOT (flushOutput ()));
flush_timer->start (FLUSH_INTERVAL);
- r_thread = new RThread ();
+ new RKRBackendProtocolFrontend (this);
+ RKRBackendProtocolFrontend::instance ()->setupBackend (QVariantMap ());
}
void RInterface::issueCommand (const QString &command, int type, const QString &rk_equiv, RCommandReceiver *receiver, int flags, RCommandChain *chain) {
@@ -107,28 +109,10 @@
RInterface::~RInterface(){
RK_TRACE (RBACKEND);
- if (r_thread->isRunning ()) {
- RK_DO (qDebug ("Waiting for R thread to finish up..."), RBACKEND, DL_INFO);
- r_thread->interruptProcessing (true);
- r_thread->kill ();
- r_thread->wait (1000);
- if (r_thread->isRunning ()) {
- RK_DO (qDebug ("Backend thread is still running. It will be killed, now."), RBACKEND, DL_WARNING);
- r_thread->terminate ();
- RK_ASSERT (false);
- }
- }
- delete r_thread;
delete flush_timer;
delete window_catcher;
}
-bool RInterface::backendIsDead () {
- RK_TRACE (RBACKEND);
-
- return (!r_thread->isRunning ());
-}
-
bool RInterface::backendIsIdle () {
RK_TRACE (RBACKEND);
@@ -137,12 +121,6 @@
return (idle);
}
-void RInterface::startThread () {
- RK_TRACE (RBACKEND);
-
- r_thread->start ();
-}
-
void RInterface::popPreviousCommand () {
RK_TRACE (RBACKEND);
@@ -220,6 +198,8 @@
}
#endif
+ if (command->type () & RCommand::QuitCommand) backend_dead = true;
+
if ((command->status & RCommand::Canceled) || (command == running_command_canceled)) {
command->status |= RCommand::HasError;
ROutput *out = new ROutput;
@@ -230,7 +210,6 @@
if (running_command_canceled) {
RK_ASSERT (command == running_command_canceled);
running_command_canceled = 0;
- r_thread->interruptProcessing (false);
locked -= locked & Cancel;
}
}
@@ -265,9 +244,8 @@
}
command_request->command = proxy;
- command_request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (command_request);
command_requests.pop_back ();
- QThread::yieldCurrentThread ();
}
void RInterface::rCommandDone (RCommand *command) {
@@ -308,19 +286,10 @@
}
}
-void RInterface::customEvent (QEvent *e) {
+void RInterface::handleRequest (RBackendRequest* request) {
RK_TRACE (RBACKEND);
- RKRBackendEvent *ev;
- if (((int) e->type ()) == ((int) RKRBackendEvent::RKWardEvent)) {
- ev = static_cast<RKRBackendEvent*> (e);
- } else {
- RK_ASSERT (false);
- return;
- }
-
flushOutput (true);
- RBackendRequest *request = ev->data ();
if (request->type == RBackendRequest::CommandOut) {
RCommandProxy *cproxy = request->command;
@@ -355,7 +324,7 @@
issueCommand ("rk.set.output.html.file (\"" + RKSettingsModuleGeneral::filesPath () + "/rk_out.html\")\n", RCommand::App | RCommand::Sync, QString (), this, SET_RUNTIME_OPTS, chain);
closeChain (chain);
- request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (request);
} else {
processRBackendRequest (request);
}
@@ -372,7 +341,7 @@
// do not trace. called periodically
// RK_TRACE (RBACKEND);
- ROutputList list = r_thread->flushOutput (forced);
+ ROutputList list = RKRBackendProtocolFrontend::instance ()->flushOutput (forced);
foreach (ROutput *output, list) {
if (all_current_commands.isEmpty ()) {
@@ -448,7 +417,7 @@
RK_ASSERT (!running_command_canceled);
locked |= Cancel;
running_command_canceled = command;
- r_thread->interruptProcessing (true);
+ RKRBackendProtocolFrontend::instance ()->interruptProcessing ();
}
}
} else {
@@ -672,7 +641,7 @@
dialog->setButtons (KDialog::Ok);
dialog->show();
- request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (request);
return;
}
}
@@ -717,10 +686,10 @@
QString message = request->params["message"].toString ();
message += i18n ("\nIt will be shut down immediately. This means, you can not use any more functions that rely on the R backend. I.e. you can do hardly anything at all, not even save the workspace (but if you're lucky, R already did that). What you can do, however, is save any open command-files, the output, or copy data out of open data editors. Quit RKWard after that.\nSince this should never happen, please write a mail to rkward-devel at lists.sourceforge.net, and tell us, what you were trying to do, when this happened. Sorry!");
KMessageBox::error (0, message, i18n ("R engine has died"));
- r_thread->kill ();
+ backend_dead = true;
}
- request->completed ();
+ RKRBackendProtocolFrontend::setRequestCompleted (request);
}
#include "rinterface.moc"
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rinterface.h 2010-11-06 20:26:20 UTC (rev 3179)
@@ -27,7 +27,7 @@
class RCommand;
class RKWardMainWindow;
class QTimer;
-class RThread;
+class RKRBackend;
struct RBackendRequest;
/** This class provides the main interface to the R-processor.
@@ -70,7 +70,7 @@
/** returns the command currently running in the thread. Be careful when using the returned pointer! */
RCommand *runningCommand () const { return (all_current_commands.isEmpty () ? 0 : all_current_commands.last ()); };
- bool backendIsDead ();
+ bool backendIsDead () { return backend_dead; };
bool backendIsIdle ();
private slots:
/** called periodically to flush output buffer in RThread */
@@ -79,7 +79,7 @@
/** Calls RThread::flushOutput(), and takes care of adding the output to all applicable commands */
void flushOutput (bool forced);
/** pointer to the RThread */
- RThread *r_thread;
+ RKRBackend *r_thread;
/** Timer to trigger flushing output */
QTimer *flush_timer;
/** canceling the command that is (or seems to be) currently running is tricky: In order to do so, we need to signal an interrupt to the RThread. We need this pointer to find out, when the command has actually been interrupted, and we can resume processing. */
@@ -120,13 +120,12 @@
QString startup_errors;
bool startup_phase2_error;
+friend class RKRBackendProtocolFrontend;
+ bool backend_dead;
friend class RKWardMainWindow;
friend class RCommand;
-/** Used (once!) to start the RThread. Need to make this separate to avoid race conditions */
- void startThread ();
protected:
-/** needed to handle the QCustomEvent s, the RThread is sending (notifications on what's happening in the backend thread) */
- void customEvent (QEvent *e);
+ void handleRequest (RBackendRequest *request);
void rCommandDone (RCommand *command);
};
Added: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol.h (rev 0)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol.h 2010-11-06 20:26:20 UTC (rev 3179)
@@ -0,0 +1,143 @@
+/***************************************************************************
+ rkrbackendprotocol - description
+ -------------------
+ begin : Thu Nov 04 2010
+ copyright : (C) 2010 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 RKRBACKENDPROTOCOL_H
+#define RKRBACKENDPROTOCOL_H
+
+#include <QVariantMap>
+#include <QObject>
+
+#include "rcommand.h"
+
+#ifndef RKWARD_SPLIT_PROCESS
+# define RKWARD_THREADED
+#endif
+
+class RKRBackendProtocolFrontend;
+class RKRBackendProtocolBackend;
+class RKRBackend;
+class RInterface;
+
+class RBackendRequest {
+public:
+ enum RCallbackType {
+ BackendExit,
+ ShowMessage,
+ ShowFiles,
+ ChooseFile,
+ EditFiles,
+ ReadLine,
+ CommandOut,
+ Started,
+ EvalRequest,
+ CallbackRequest,
+ HistoricalSubstackRequest,
+ OtherRequest /**< Any other type of request. Note: which requests are in the enum, and which are not has mostly historical reasons. @see params */
+ };
+
+ RBackendRequest (bool synchronous, RCallbackType type) {
+ RBackendRequest::synchronous = synchronous;
+ RBackendRequest::type = type;
+ done = false;
+ command = 0;
+ }
+ ~RBackendRequest () {};
+
+/** Should this request be handled synchronously? False by default. */
+ bool synchronous;
+/** For synchronous requests, only: The frontend-thread will set this to true (using completed()), once the request has been "completed". Important: The backend thread MUST NOT touch a request after it has been sent, and before "done" has been set to true. */
+ bool done;
+ RCallbackType type;
+/** For synchronous requests, only: If the the frontend wants any commands to be executed, it will place the next one in this slot. The backend thread should keep executing commands (in a sub-eventloop) while this is non-zero. Also, the backend-thread may place here any command that has just finished. */
+ RCommandProxy *command;
+/** Any other parameters, esp. for RCallbackType::OtherRequest. Can be used in both directions. */
+ QVariantMap params;
+protected:
+ friend class RKRBackendProtocolFrontend;
+ friend class RKRBackendProtocolBackend;
+
+ void completed () {
+ if (!synchronous) delete this;
+ else done = true;
+ }
+
+ RBackendRequest *duplicate () {
+ RBackendRequest* ret = new RBackendRequest (synchronous, type);
+ ret->done = done;
+ ret->command = command;
+ ret->params = params;
+ return ret;
+ }
+};
+
+#ifdef RKWARD_THREADED
+# include <QEvent>
+ /** Simple event class to relay information from the RKRBackend to the main thread. This is basically like QCustomEvent in Qt3*/
+ class RKRBackendEvent : public QEvent {
+ public:
+ enum EventType {
+ RKWardEvent = QEvent::User + 1
+ };
+ RKRBackendEvent (RBackendRequest* data=0) : QEvent ((QEvent::Type) RKWardEvent) { _data = data; };
+ RKRBackendEvent ();
+
+ RBackendRequest* data () { return _data; };
+ private:
+ RBackendRequest* _data;
+ };
+#endif
+
+class RKRBackendProtocolFrontend : public QObject {
+public:
+ RKRBackendProtocolFrontend (RInterface* parent);
+ ~RKRBackendProtocolFrontend ();
+
+ static void setRequestCompleted (RBackendRequest *request);
+ ROutputList flushOutput (bool force);
+ void interruptProcessing ();
+ void terminateBackend ();
+ void setupBackend (QVariantMap backend_params);
+ static RKRBackendProtocolFrontend* instance () { return _instance; };
+protected:
+#ifdef RKWARD_THREADED
+/** needed to handle the QEvents, the R thread is sending (notifications on what's happening in the backend thread) */
+ void customEvent (QEvent *e);
+#endif
+private:
+ static RKRBackendProtocolFrontend* _instance;
+ RInterface *frontend;
+};
+
+class RKRBackendProtocolBackend {
+public:
+ static bool inRThread ();
+protected:
+friend class RKRBackendProtocolFrontend;
+friend class RKRBackend;
+friend class RKRBackendThread;
+ RKRBackendProtocolBackend ();
+ ~RKRBackendProtocolBackend ();
+
+ void sendRequest (RBackendRequest *request);
+ static void msleep (int delay);
+ static void interruptProcessing ();
+ static RKRBackendProtocolBackend* instance () { return _instance; };
+private:
+ static RKRBackendProtocolBackend* _instance;
+};
+
+#endif
Added: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp (rev 0)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_backend.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -0,0 +1,151 @@
+/***************************************************************************
+ rkrbackendprotocol - description
+ -------------------
+ begin : Thu Nov 04 2010
+ copyright : (C) 2010 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 "rkrbackendprotocol.h"
+
+#include "rembedinternal.h"
+
+#include "../debug.h"
+
+#ifdef RKWARD_THREADED
+# ifndef Q_WS_WIN
+# include <signal.h> // needed for pthread_kill
+# include <pthread.h> // seems to be needed at least on FreeBSD
+# endif
+# include <QThread>
+# include <QApplication>
+#else
+# include <unistd.h>
+#endif
+
+#ifdef RKWARD_THREADED
+ class RKRBackendThread : public QThread {
+ public:
+ RKRBackendThread () {
+# ifdef Q_WS_WIN
+ // we hope that on other platforms the default is reasonable
+ setStackSize (0xa00000); // 10MB as recommended by r_exts-manual
+# endif
+ instance = this;
+ };
+ ~RKRBackendThread () {};
+
+ // called form the *other* thread, only
+ void exitThread () {
+ if (isRunning ()) {
+ RK_DO (qDebug ("Waiting for R thread to finish up..."), RBACKEND, DL_INFO);
+ RKRBackendProtocolBackend::interruptProcessing ();
+ RKRBackend::this_pointer->kill ();
+ wait (1000);
+ if (isRunning ()) {
+ RK_DO (qDebug ("Backend thread is still running. It will be killed, now."), RBACKEND, DL_WARNING);
+ terminate ();
+ yieldCurrentThread ();
+ RK_ASSERT (false);
+ }
+ }
+ };
+
+ void publicmsleep (int delay) { msleep (delay); };
+
+ void run () {
+ thread_id = currentThreadId ();
+ RKRBackend::this_pointer->run ();
+ }
+
+ /** 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;
+ static RKRBackendThread* instance;
+ };
+ RKRBackendThread* RKRBackendThread::instance = 0;
+#else
+#error
+#endif
+
+RKRBackendProtocolBackend* RKRBackendProtocolBackend::_instance = 0;
+RKRBackendProtocolBackend::RKRBackendProtocolBackend () {
+ RK_TRACE (RBACKEND);
+
+ _instance = this;
+ new RKRBackend ();
+#ifdef RKWARD_THREADED
+ new RKRBackendThread ();
+ RKRBackendThread::instance->start ();
+#else
+#error
+#endif
+}
+
+RKRBackendProtocolBackend::~RKRBackendProtocolBackend () {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ RKRBackendThread::instance->exitThread ();
+ delete RKRBackendThread::instance;
+#else
+#error
+#endif
+}
+
+void RKRBackendProtocolBackend::sendRequest (RBackendRequest *_request) {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ RBackendRequest* request = _request;
+ if (!request->synchronous) {
+ request = _request->duplicate (); // the instance we send to the frontend will remain in there, and be deleted, there
+ _request->done = true; // for aesthetics
+ }
+
+ RKRBackendEvent* event = new RKRBackendEvent (request);
+ qApp->postEvent (RKRBackendProtocolFrontend::instance (), event);
+#else
+#error
+#endif
+}
+
+bool RKRBackendProtocolBackend::inRThread () {
+#ifdef RKWARD_THREADED
+ return (QThread::currentThread () == RKRBackendThread::instance);
+#else
+#error
+#endif
+}
+
+void RKRBackendProtocolBackend::msleep (int delay) {
+# ifdef RKWARD_THREADED
+ RKRBackendThread::instance->publicmsleep (delay);
+#else
+ usleep (delay * 1000);
+#endif
+}
+
+void RKRBackendProtocolBackend::interruptProcessing () {
+ if (inRThread ()) {
+ RKRBackend::scheduleInterrupt ();
+ } else {
+#ifdef Q_WS_WIN
+ RKRBackend::scheduleInterrupt ();
+#else
+# ifdef RKWARD_THREADED
+ pthread_kill ((pthread_t) RKRBackendThread::instance->thread_id, SIGUSR1); // relays to SIGINT
+# else
+# error
+# endif
+ }
+#endif
+}
Added: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp (rev 0)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrbackendprotocol_frontend.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -0,0 +1,110 @@
+/***************************************************************************
+ rkrbackendprotocol - description
+ -------------------
+ begin : Thu Nov 04 2010
+ copyright : (C) 2010 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 "rkrbackendprotocol.h"
+
+#include "rinterface.h"
+#ifdef RKWARD_THREADED
+# include <QThread>
+# include "rembedinternal.h"
+#endif
+
+#include "../debug.h"
+
+RKRBackendProtocolFrontend* RKRBackendProtocolFrontend::_instance = 0;
+RKRBackendProtocolFrontend::RKRBackendProtocolFrontend (RInterface* parent) : QObject (parent) {
+ RK_TRACE (RBACKEND);
+
+ RK_ASSERT (!_instance);
+ frontend = parent;
+ _instance = this;
+}
+
+RKRBackendProtocolFrontend::~RKRBackendProtocolFrontend () {
+ RK_TRACE (RBACKEND);
+
+ terminateBackend ();
+ delete RKRBackendProtocolBackend::instance ();
+}
+
+void RKRBackendProtocolFrontend::setupBackend (QVariantMap backend_params) {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ new RKRBackendProtocolBackend ();
+#else
+#error
+#endif
+}
+
+void RKRBackendProtocolFrontend::setRequestCompleted (RBackendRequest *request) {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ bool sync = request->synchronous;
+ request->completed ();
+ if (sync) QThread::yieldCurrentThread ();
+#else
+#error
+#endif
+}
+
+ROutputList RKRBackendProtocolFrontend::flushOutput (bool force) {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ return (RKRBackend::this_pointer->flushOutput (force));
+#else
+#error
+#endif
+}
+
+void RKRBackendProtocolFrontend::interruptProcessing () {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ RK_ASSERT (!RKRBackendProtocolBackend::inRThread ());
+ RKRBackendProtocolBackend::interruptProcessing ();
+#else
+ kill (SIGUSR1, pid_of_it);
+#error
+#endif
+}
+
+void RKRBackendProtocolFrontend::terminateBackend () {
+ RK_TRACE (RBACKEND);
+
+#ifdef RKWARD_THREADED
+ RKRBackend::this_pointer->kill ();
+#else
+ kill (SIGUSR2, pid_of_it);
+#error
+#endif
+}
+
+#ifdef RKWARD_THREADED
+void RKRBackendProtocolFrontend::customEvent (QEvent *e) {
+qDebug ("got it");
+ if (((int) e->type ()) == ((int) RKRBackendEvent::RKWardEvent)) {
+ RKRBackendEvent *ev = static_cast<RKRBackendEvent*> (e);
+ frontend->handleRequest (ev->data ());
+ } else {
+ RK_ASSERT (false);
+ return;
+ }
+}
+#endif
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrsupport.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrsupport.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkrsupport.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -116,7 +116,7 @@
} else if (IS_LATIN1 (dummy)) {
list.append (QString::fromLatin1 ((char *) STRING_PTR (dummy)));
} else {
- list.append (RThread::this_pointer->current_locale_codec->toUnicode ((char *) STRING_PTR (dummy)));
+ list.append (RKRBackend::this_pointer->current_locale_codec->toUnicode ((char *) STRING_PTR (dummy)));
}
}
}
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rksignalsupport.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -69,10 +69,10 @@
RK_ASSERT (signum == SIGSEGV);
}
- RThread::tryToDoEmergencySave ();
+ RKRBackend::tryToDoEmergencySave ();
// if we are not in the R thread, handling the signal in R does more harm than good.
- if (RThread::inRThread ()) {
+ if (RKRBackendProtocolBackend::inRThread ()) {
#ifdef Q_WS_WIN
if (r_handler) {
r_handler (signum);
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkstructuregetter.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkstructuregetter.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rkstructuregetter.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -83,7 +83,6 @@
// TODO: accept an envlevel parameter
envir_depth = INTEGER (envlevel)[0];
- unsigned int count;
QString name_string = RKRSupport::SEXPToString (name);
// resolve namespace, if needed
@@ -172,7 +171,6 @@
bool is_container = false;
bool is_environment = false;
unsigned int type = 0;
- unsigned int count;
RK_DO (qDebug ("fetching '%s': %p, s-type %d", name.toLatin1().data(), val, TYPEOF (val)), RBACKEND, DL_DEBUG);
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rthread.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -16,7 +16,7 @@
***************************************************************************/
#include "rembedinternal.h"
-#include "rinterface.h"
+#include "rkrbackendprotocol.h"
#include "../rkglobals.h"
#include "../version.h"
@@ -25,26 +25,11 @@
#include <QCoreApplication>
#include <klocale.h>
-#ifndef Q_WS_WIN
-# include <signal.h> // needed for pthread_kill
-# include <pthread.h> // seems to be needed at least on FreeBSD
-#endif
-
#define MAX_BUF_LENGTH 16000
#define OUTPUT_STRING_RESERVE 1000
-void RThread::interruptProcessing (bool interrupt) {
- if (!interrupt) return;
-#ifdef Q_WS_WIN
- RK_scheduleIntr ();
-#else
- pthread_kill ((pthread_t) thread_id, SIGUSR1); // relays to SIGINT
-#endif
-}
-
-void RThread::run () {
+void RKRBackend::run () {
RK_TRACE (RBACKEND);
- thread_id = currentThreadId ();
killed = NotKilled;
previous_command = 0;
@@ -53,7 +38,7 @@
enterEventLoop ();
}
-void RThread::commandFinished (bool check_object_updates_needed) {
+void RKRBackend::commandFinished (bool check_object_updates_needed) {
RK_TRACE (RBACKEND);
RK_DO (qDebug ("done running command"), RBACKEND, DL_DEBUG);
@@ -70,20 +55,14 @@
if (!all_current_commands.isEmpty ()) current_command = all_current_commands.last ();
}
-RCommandProxy* RThread::handleRequest (RBackendRequest *_request, bool mayHandleSubstack) {
+RCommandProxy* RKRBackend::handleRequest (RBackendRequest *request, bool mayHandleSubstack) {
RK_TRACE (RBACKEND);
- RK_ASSERT (_request);
+ RK_ASSERT (request);
- RBackendRequest* request = _request;
- bool synchronous = request->synchronous; // It's important to *copy* this. For async requests, the request instance may be deleted right after sending.
- if (!synchronous) request = request->duplicate (); // will remain in the frontend, and be deleted, there
+ RKRBackendProtocolBackend::instance ()->sendRequest (request);
- RKRBackendEvent* event = new RKRBackendEvent (request);
- qApp->postEvent (RKGlobals::rInterface (), event);
-
- if (!synchronous) {
+ if (!request->synchronous) {
RK_ASSERT (mayHandleSubstack); // i.e. not called from fetchNextCommand
- _request->done = true; // for aesthetics
return 0;
}
@@ -91,7 +70,7 @@
if (killed) return 0;
// NOTE: processX11Events() may, conceivably, lead to new requests, which may also wait for sub-commands!
processX11Events ();
- if (!request->done) msleep (1);
+ if (!request->done) RKRBackendProtocolBackend::msleep (1);
}
RCommandProxy* command = request->command;
@@ -112,7 +91,7 @@
return 0;
}
-RCommandProxy* RThread::fetchNextCommand () {
+RCommandProxy* RKRBackend::fetchNextCommand () {
RK_TRACE (RBACKEND);
RBackendRequest req (true, RBackendRequest::CommandOut);
@@ -122,15 +101,15 @@
return (handleRequest (&req, false));
}
-void RThread::waitIfOutputBufferExceeded () {
+void RKRBackend::waitIfOutputBufferExceeded () {
// don't trace
while (out_buf_len > MAX_BUF_LENGTH) {
if (isKilled ()) return; // don't block. Frontend could be crashed
- msleep (10);
+ RKRBackendProtocolBackend::msleep (10);
}
}
-void RThread::handleOutput (const QString &output, int buf_length, ROutput::ROutputType output_type) {
+void RKRBackend::handleOutput (const QString &output, int buf_length, ROutput::ROutputType output_type) {
if (!buf_length) return;
RK_TRACE (RBACKEND);
@@ -157,7 +136,7 @@
output_buffer_mutex.unlock ();
}
-ROutputList RThread::flushOutput (bool forcibly) {
+ROutputList RKRBackend::flushOutput (bool forcibly) {
ROutputList ret;
if (out_buf_len == 0) return ret; // if there is absolutely no output, just skip.
@@ -179,7 +158,7 @@
return ret;
}
-void RThread::handleHistoricalSubstackRequest (const QStringList &list) {
+void RKRBackend::handleHistoricalSubstackRequest (const QStringList &list) {
RK_TRACE (RBACKEND);
RBackendRequest request (true, RBackendRequest::HistoricalSubstackRequest);
@@ -187,7 +166,7 @@
handleRequest (&request);
}
-void RThread::initialize () {
+void RKRBackend::initialize () {
RK_TRACE (RBACKEND);
// in RInterface::RInterface() we have created a fake RCommand to capture all the output/errors during startup. Fetch it
@@ -225,7 +204,7 @@
repl_status.eval_depth--;
}
-void RThread::checkObjectUpdatesNeeded (bool check_list) {
+void RKRBackend::checkObjectUpdatesNeeded (bool check_list) {
RK_TRACE (RBACKEND);
if (killed) return;
Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rkward.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rkward.cpp 2010-11-04 16:26:26 UTC (rev 3178)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rkward.cpp 2010-11-06 20:26:20 UTC (rev 3179)
@@ -297,8 +297,6 @@
new RObjectList ();
connect (RObjectList::getObjectList (), SIGNAL (workspaceUrlChanged(const KUrl&)), this, SLOT (addWorkspaceUrl(const KUrl&)));
- RKGlobals::rInterface ()->startThread ();
-
RObjectBrowser::mainBrowser ()->unlock ();
}
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