# [rkward-cvs] rkward/rkward/rbackend rembedinternal.cpp,1.24,1.25 rembedinternal.h,1.14,1.15 rinterface.h,1.20,1.21 rthread.h,1.17,1.18

Thomas Friedrichsmeier tfry at users.sourceforge.net
Fri Oct 21 15:23:38 UTC 2005

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

Modified Files:
Log Message:
Make windows detachable. Some more work needs to be done, but basically functioning

Index: rembedinternal.cpp
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rembedinternal.cpp,v
retrieving revision 1.24
retrieving revision 1.25
diff -C2 -d -r1.24 -r1.25
*** rembedinternal.cpp	18 Oct 2005 15:53:26 -0000	1.24
--- rembedinternal.cpp	21 Oct 2005 15:23:36 -0000	1.25
***************
*** 40,44 ****
#include "../rkglobals.h"

! /// ############## R Standard callback overrides BEGIN ####################
void RSuicide (char* message) {
RCallbackArgs args;
--- 40,44 ----
#include "../rkglobals.h"

! // ############## R Standard callback overrides BEGIN ####################
void RSuicide (char* message) {
RCallbackArgs args;
***************
*** 171,175 ****
}

! /// ############## R Standard callback overrides END ####################

REmbedInternal::REmbedInternal() {
--- 171,175 ----
}

! // ############## R Standard callback overrides END ####################

REmbedInternal::REmbedInternal() {

Index: rembedinternal.h
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rembedinternal.h,v
retrieving revision 1.14
retrieving revision 1.15
diff -C2 -d -r1.14 -r1.15
*** rembedinternal.h	18 Oct 2005 15:53:26 -0000	1.14
--- rembedinternal.h	21 Oct 2005 15:23:36 -0000	1.15
***************
*** 36,68 ****
} type;

! 	char **chars_a;
! 	char **chars_b;
! 	char **chars_c;
! 	char **chars_d;
! 	int int_a;
! 	int int_b;
! 	int int_c;
! 	bool bool_a;
};

!  /** The main purpose of separating this class from REmbed is that R- and Qt-includes don't go together well. Hence this class is Qt-agnostic while
! 	REmbed is essentially R-agnostic.

! 	@see REmbed

*@author Thomas Friedrichsmeier
!   */
!
class REmbedInternal {
public:
! /** constructor. You can't create an instance of this class do to pure virtual functions. Create an instance of REmbed instead. */
! 	REmbedInternal();
/** destructor */
! 	virtual ~REmbedInternal();

/** connect R standard callbacks */
void connectCallbacks ();

! /** Enum specifying types of errors that may occur while parsing/evaluation a command in R */
enum RKWardRError {
NoError=0,			/**< No error */
--- 36,67 ----
} type;

! 	char **chars_a;		/**< a char** parameter. Look at the respective callbacks to find out, what it is used for. */
! 	char **chars_b;		/**< a char** parameter. Look at the respective callbacks to find out, what it is used for. */
! 	char **chars_c;		/**< a char** parameter. Look at the respective callbacks to find out, what it is used for. */
! 	char **chars_d;		/**< a char** parameter. Look at the respective callbacks to find out, what it is used for. */
! 	int int_a;		/**< an int parameter. Look at the respective callbacks to find out, what it is used for. */
! 	int int_b;		/**< an int parameter. Look at the respective callbacks to find out, what it is used for. */
! 	int int_c;		/**< an int parameter. Look at the respective callbacks to find out, what it is used for. */
! 	bool bool_a;		/**< a bool parameter. Look at the respective callbacks to find out, what it is used for. */
};

!  /** The main purpose of separating this class from RThread is that R- and Qt-includes don't go together well. Hence this class is Qt-agnostic while

*@author Thomas Friedrichsmeier
! */
class REmbedInternal {
public:
! /** constructor. You can't create an instance of this class due to pure virtual functions. Create an instance of RThread instead. */
! 	REmbedInternal ();
/** destructor */
! 	virtual ~REmbedInternal ();

/** connect R standard callbacks */
void connectCallbacks ();

! /** Enum specifying types of errors that may occur while parsing/evaluating a command in R */
enum RKWardRError {
NoError=0,			/**< No error */
***************
*** 72,76 ****
};

! /** clean shutdown of R. If suicidal, perform only the most basic shutdown operations */
void shutdown (bool suicidal);
protected:
--- 71,76 ----
};

! /** clean shutdown of R.
! @param suicidal if true, perform only the most basic shutdown operations */
void shutdown (bool suicidal);
protected:
***************
*** 82,111 ****
/** low-level running of a command.
@param command char* of the command to be run
! @param error this will be set to a value in RKWardError depending on success/failure or the command
@param print_result whether the R_Visible flag should be set. If true, R will behave mostly as if in a regular console session. Otherwise values
will only be printed if called for expressedly with print ("...") or similar. */
void runCommandInternal (const char *command, RKWardRError *error, bool print_result=false);
-
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of char* after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set.
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure or the command
@returns an array of char* or 0 on failure
@see RCommand::GetStringVector */
char **getCommandAsStringVector (const char *command, int *count, RKWardRError *error);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of double after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set.
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure or the command
@returns an array of double or 0 on failure
@see RCommand::GetRealVector */
double *getCommandAsRealVector (const char *command, int *count, RKWardRError *error);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of int after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set.
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure or the command
@returns an array of int or 0 on failure
@see RCommand::GetIntVector */
--- 82,110 ----
/** low-level running of a command.
@param command char* of the command to be run
! @param error this will be set to a value in RKWardError depending on success/failure of the command
@param print_result whether the R_Visible flag should be set. If true, R will behave mostly as if in a regular console session. Otherwise values
will only be printed if called for expressedly with print ("...") or similar. */
void runCommandInternal (const char *command, RKWardRError *error, bool print_result=false);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of char* after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set. @see RCommand::GetStringVector
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure of the command
@returns an array of char* or 0 on failure
@see RCommand::GetStringVector */
char **getCommandAsStringVector (const char *command, int *count, RKWardRError *error);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of double after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set. @see RCommand::GetRealVector
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure of the command
@returns an array of double or 0 on failure
@see RCommand::GetRealVector */
double *getCommandAsRealVector (const char *command, int *count, RKWardRError *error);
/** basically a wrapper to runCommandInternal (). Tries to convert the result of the command to an array of int after running the command. Since
! this will not ever be done for user commands, the R_Visible flag will never be set.  @see RCommand::GetIntVector
@param command char* of the command to be run
@param count length of array returned
! @param error this will be set to a value in RKWardError depending on success/failure of the command
@returns an array of int or 0 on failure
@see RCommand::GetIntVector */
***************
*** 115,119 ****
static void processX11Events ();

! /** This gets called, on normal R output (R_WriteConsole). Used to get at output. */
virtual void handleOutput (char *buf, int buf_length) = 0;

--- 114,118 ----
static void processX11Events ();

! /** This gets called on normal R output (R_WriteConsole). Used to get at output. */
virtual void handleOutput (char *buf, int buf_length) = 0;

***************
*** 125,135 ****

/** The main callback from R to rkward. Since we need QStrings and stuff to handle the requests, this is only a pure virtual function. The real
! implementation is in REmbed::handleSubstackCall () */
virtual void handleSubstackCall (char **call, int call_length) = 0;

/** This second callback handles R standard callbacks. The difference to the first one is, that these are typically required to finish within the same
! functions. On the other hand, also, they don't require further computations in R, and hence no full-fledged substack.

! Otherwise it is very similar to handleSubstackCall (), esp. in that is implemented in REmbed::handleStandardCallback () */
virtual void handleStandardCallback (RCallbackArgs *args) = 0;

--- 124,135 ----

/** The main callback from R to rkward. Since we need QStrings and stuff to handle the requests, this is only a pure virtual function. The real
! implementation is in RThread::handleSubstackCall () */
virtual void handleSubstackCall (char **call, int call_length) = 0;

/** This second callback handles R standard callbacks. The difference to the first one is, that these are typically required to finish within the same
! function. On the other hand, also, they don't require further computations in R, and hence no full-fledged substack.

! Otherwise it is very similar to handleSubstackCall (), esp. in that is implemented in RThread::handleStandardCallback ()
! @see RCallbackArgs @see RCallbackType */
virtual void handleStandardCallback (RCallbackArgs *args) = 0;

===================================================================
retrieving revision 1.17
retrieving revision 1.18
diff -C2 -d -r1.17 -r1.18
*** rthread.h	14 Oct 2005 15:57:43 -0000	1.17
--- rthread.h	21 Oct 2005 15:23:36 -0000	1.18
***************
*** 42,57 ****

Actually, there are really two copies of the main loop: The regular one, and a second one which gets run when the R backend has requested some
! task to be carried out. In this case, we might have to run some further child commands in the backend, before we proceed with the commands in
the main queque. Some thing like:

! - Run some R commands
- R backend asks for some information / action
! 		- potentially some more R commands are needed to accomplish this request
- return the result
- R backend request completed
! - Run some more R commands

! This subordinate/nested eventloop is done in doSubstack ().

A closely related class is RInterface: RThread communicates with RInterface by placing QCustomEvent s, when commands are done
--- 42,57 ----

Actually, there are really two copies of the main loop: The regular one, and a second one which gets run when the R backend has requested some
! task to be carried out (@see handleSubstackCall). In this case, we might have to run some further child commands in the backend, before we proceed with the commands in
the main queque. Some thing like:

! - Run some RCommand s
- R backend asks for some information / action
! 		- potentially some more RCommand s are needed to accomplish this request
- return the result
- R backend request completed
! - Run some more RCommand s

! This subordinate/nested eventloop is done in handleSubstackCall ().

A closely related class is RInterface: RThread communicates with RInterface by placing QCustomEvent s, when commands are done
***************
*** 139,144 ****
/** This is the function in which an RCommand actually gets processed. Basically it passes the command to REmbedInteranl::runCommandInternal () and sends RInterface some events about what is currently happening. */
void doCommand (RCommand *command);
!
int locked;
bool killed;
};
--- 139,145 ----
/** This is the function in which an RCommand actually gets processed. Basically it passes the command to REmbedInteranl::runCommandInternal () and sends RInterface some events about what is currently happening. */
void doCommand (RCommand *command);
! /** 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;
};

Index: rinterface.h
===================================================================
RCS file: /cvsroot/rkward/rkward/rkward/rbackend/rinterface.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** rinterface.h	14 Oct 2005 15:57:43 -0000	1.20
--- rinterface.h	21 Oct 2005 15:23:36 -0000	1.21
***************
*** 41,46 ****

@see RCommand
!   *@author Thomas Friedrichsmeier
!   */

class RInterface : public QObject {
--- 41,46 ----

@see RCommand
! 	*@author Thomas Friedrichsmeier
! */

class RInterface : public QObject {
***************
*** 69,72 ****
--- 69,73 ----
void pauseProcessing (bool pause);

+ /** *The* mutex in usein RKWard. This is needed to ensure, the main (GUI) thread, and the backend thread (@see RThread) do not try to access the same data at the same time. Use MUTEX_LOCK and MUTEX_UNLOCK to lock/unlock the mutex. */
static QMutex mutex;
//static int mutex_counter;
***************
*** 75,79 ****
--- 76,82 ----
RCommand *runningCommand () { return r_thread->current_command; };
private:
+ /** pointer to the RThread */
+ /** cancelling 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. */
RCommand *running_command_canceled;

***************
*** 84,89 ****
--- 87,94 ----
void processRCallbackRequest (RCallbackArgs *args);
friend class RKwardApp;
+ /** pointer to the RKwatch. TODO: (re-)move this pointer */
RKwatch *watch;
protected:
+ /** needed to handle the QCustomEvent s, the RThread is sending (notifications on what's happening in the backend thread) */
void customEvent (QCustomEvent *e);
};
***************
*** 94,98 ****

This page tries to give you an introduction into using the RInterface and related classes. You'll learn how to submit a command for evaluation
! by R and how you can get and handle the results. Note that is fairly low-level. You do not need to read this documentation in order to develop
plugins. You'll only need to know this in order to do C++-hacking in rkward.
The page is divided into several sections on special problems, but if you're new to rkward, you will probably want to read it as a whole instead of
--- 99,103 ----

This page tries to give you an introduction into using the RInterface and related classes. You'll learn how to submit a command for evaluation
! by R and how you can get and handle the results. Note that this is fairly low-level. You do not need to read this documentation in order to develop
plugins. You'll only need to know this in order to do C++-hacking in rkward.
The page is divided into several sections on special problems, but if you're new to rkward, you will probably want to read it as a whole instead of
***************
*** 109,113 ****
#include "rbackend/rinterface.h"

! RKGlobals::rInter->issueCommand ("print (\"hello world!\")", RCommand::User);
\endcode

--- 114,118 ----
#include "rbackend/rinterface.h"

! RKGlobals::rInterface ()->issueCommand ("print (\"hello world!\")", RCommand::User);
\endcode

***************
*** 115,129 ****
parameters as argument. It is actually quite similar to the other RInterface::issueCommand function which takes an RCommand as a paramter. This convenience class basically just creates an RCommand with the same parameters as the constructor of RCommand (RCommand::RCommand), and then submits this RCommand. We'll discuss what an RCommand really is further down below. For now a good enough explanations is, that it's simply a container for a command.

! The first parameter here, is fairly obvious, the command-string the R backend should evaluate.

! The second parameter (RCommand::User) is and integer, which can be a bit-wise or-able combination of the values in the RCommand::CommandTypes enum. We'll deal with the more specific values in that enum later. Here, were just using RCommand::User, which signifies, that the command came
directly from the user. This information is fairly important, as it affects the handling of the command at several places: Which color it will be given in
! the R-command log (currently class RKWatch), whether the command can be cancelled (RCommand::User commands can be cancelled, but some other types of commands can not be cancelled), etc. See the documentation on RCommand::CommandTypes (not yet complete) for more information.

\section UsingTheInterfaceToRHandlingReturns A slightly more realistic example: Handling the result of an RCommand

! Most of the time you don't just want to run a command, but you also want to know the result. Now, this is a tad bit more difficult than one might expect at first glance. The reason for this is, that the R backend runs in a separate thread. Hence, whenever you submit a command, it generally does not get executed right away - or at least you just don't know, when exactly it gets executed, and when the result is available. This is neccessary, so (expensive) commands running in the backend do not block operations in the GUI/frontend.

! Ok, so how do you get informed, when you command was completed? Using RCommandReceiver. What you will want to do is inherit the class you
want to handle the results of RCommands from RCommandReceiver. When finished, the RCommand will be submitted to the (pure virtual) RCommandReceiver::rCommandDone function, which of course you'll have to implement in a meaningful way in your derived class.

--- 120,134 ----
parameters as argument. It is actually quite similar to the other RInterface::issueCommand function which takes an RCommand as a paramter. This convenience class basically just creates an RCommand with the same parameters as the constructor of RCommand (RCommand::RCommand), and then submits this RCommand. We'll discuss what an RCommand really is further down below. For now a good enough explanations is, that it's simply a container for a command.

! The first parameter here is fairly obvious, the command-string the R backend should evaluate.

! The second parameter (RCommand::User) is an integer, which can be a bit-wise or-able combination of the values in the RCommand::CommandTypes enum. We'll deal with the more specific values in that enum later. Here, we're just using RCommand::User, which signifies, that the command came
directly from the user. This information is fairly important, as it affects the handling of the command at several places: Which color it will be given in
! the R-command log (currently class RKwatch), whether the command can be cancelled (RCommand::User commands can be cancelled, but some other types of commands can not be cancelled), etc. See the documentation on RCommand::CommandTypes (not yet complete) for more information.

\section UsingTheInterfaceToRHandlingReturns A slightly more realistic example: Handling the result of an RCommand

! Most of the time you don't just want to run a command, but you also want to know the result. Now, this is a tad bit more difficult than one might expect at first glance. The reason for this is that the R backend runs in a separate thread. Hence, whenever you submit a command, it generally does not get executed right away - or at least you just don't know, when exactly it gets executed, and when the result is available. This is neccessary, so (expensive) commands running in the backend do not block operations in the GUI/frontend.

! Ok, so how do you get informed, when your command was completed? Using RCommandReceiver. What you will want to do is inherit the class you
want to handle the results of RCommands from RCommandReceiver. When finished, the RCommand will be submitted to the (pure virtual) RCommandReceiver::rCommandDone function, which of course you'll have to implement in a meaningful way in your derived class.

***************
*** 149,153 ****

! 	RKGlobals::rInter->issueCommand ("print (1+1)", RCommand::App, QString::null, this);
}

--- 154,158 ----

! 	RKGlobals::rInterface ()->issueCommand ("print (1+1)", RCommand::App, QString::null, this);
}

***************
*** 165,169 ****
\section UsingTheInterfaceToRMultipleCommands Dealing with several RCommands in the same object

! In many cases you don't just want to deal with a single RCommand in an RCommandReceiver, but rather you might submit a bunch of different command (for instance to find out about several different properties of an object in R-space), and then use some special handling for each of those commands. So the problem is, how to find out, which of your commands you're currently dealing with in rCommandDone.

There are several ways to deal with this:
--- 170,174 ----
\section UsingTheInterfaceToRMultipleCommands Dealing with several RCommands in the same object

! In many cases you don't just want to deal with a single RCommand in an RCommandReceiver, but rather you might submit a bunch of different commands (for instance to find out about several different properties of an object in R-space), and then use some special handling for each of those commands. So the problem is, how to find out, which of your commands you're currently dealing with in rCommandDone.

There are several ways to deal with this:
***************
*** 207,211 ****
First the RCommand is placed in a first-in-first-out stack. This stack is needed, since - as discussed - the commands get executed in a separate thread, so several command may get stacked up, before the first one gets run.

! Then, in the backend thread (RThread) there is a loop running, which fetches those commands from the stack and executes them one by one. Whenver a command has been executed in this thread, it gets updated with information on any errors that occurred and of course also with the result of running the command. Next, a QCustomEvent is being posted. What this does is basically, transfer the pointer to the command back to the main thread in a safe way.

Whenever the main thread becomes active again, it will find that QCustomEvent and handle it in RInterface::customEvent.
--- 212,216 ----
First the RCommand is placed in a first-in-first-out stack. This stack is needed, since - as discussed - the commands get executed in a separate thread, so several command may get stacked up, before the first one gets run.

! Then, in the backend thread (RThread) there is a loop running, which fetches those commands from the stack and executes them one by one. Whenver a command has been executed in this thread, it gets updated with information on any errors that occurred and of course also with the result of running the command. Next, a QCustomEvent is being posted. What this does is - rougly speaking -, transfer the pointer to the command back to the main thread in a safe way.

Whenever the main thread becomes active again, it will find that QCustomEvent and handle it in RInterface::customEvent.
***************
*** 253,257 ****
\section UsingTheInterfaceToRCommandChains How to ensure commands get executed in the correct order: RCommandChain

! The way to do this is to use RCommandChain. Basically, when you want command to be executed in a sequence being sure that no other commands intervene, you do this:

\code
--- 258,262 ----
\section UsingTheInterfaceToRCommandChains How to ensure commands get executed in the correct order: RCommandChain

! The way to do this is to use RCommandChain. Basically, when you want commands to be executed in a sequence being sure that no other commands intervene, you do this:

\code
***************
*** 292,296 ****
- some_command2

! You can also open sub chains, using

\code
--- 297,301 ----
- some_command2

! So the order of execution will be guaranteed to be first_command, second_command, some_command, some_command2, although they were issued ina different order. You can also open sub chains, using

\code
***************
*** 302,308 ****
\section UsingTheInterfaceToROutputOptions Sending results to the output and retrieving low-level data from the backend

! There are a few special type-modifiers you can specify when creating and RCommand (as part of the second parameter to RCommand::RCommand or RInterface::issueCommand), that determine what will be done with the result:

! - RCommand::EmtpyCommand
This one tells the backend, that the command does not really need to be executed, and does not contain anything. You'll rarely need this flag, but sometimes it is useful to submit an empty command simply to find out when it is finished.

--- 307,313 ----
\section UsingTheInterfaceToROutputOptions Sending results to the output and retrieving low-level data from the backend

! There are a few special type-modifiers you can specify when creating an RCommand (as part of the second parameter to RCommand::RCommand or RInterface::issueCommand), that determine what will be done with the result:

! - RCommand::EmptyCommand
This one tells the backend, that the command does not really need to be executed, and does not contain anything. You'll rarely need this flag, but sometimes it is useful to submit an empty command simply to find out when it is finished.

***************
*** 311,318 ****

- RCommand::GetIntVector, RCommand::GetStringVector, RCommand::GetRealVector
! These are special modifiers helpful when transferring data from R to RKWard (used primarily in the editor classes and in conjunction with RCommand::Sync): They tell the backend to try to fetch the result as and array of int, char*, or double, respectively. For instance, if you know object "myobject" is an integer vector, you may get the data using

\code
! RKGlobals::rInterface ()->issueCommand ("myobject", RCommand::Sync | RCommand::GetIntVector, QString::null,this);
\endcode

--- 316,323 ----

- RCommand::GetIntVector, RCommand::GetStringVector, RCommand::GetRealVector
! These are special modifiers helpful when transferring data from R to RKWard (used primarily in the editor classes and in conjunction with RCommand::Sync): They tell the backend to try to fetch the result as an array of int, char*, or double, respectively. For instance, if you know object "myobject" is an integer vector, you may get the data using

\code
! RKGlobals::rInterface ()->issueCommand ("myobject", RCommand::Sync | RCommand::GetIntVector, QString::null, this);
\endcode

***************
*** 334,337 ****
--- 339,347 ----
- \ref RCommandStack

+ Even lower level API:
+