]> git.lyx.org Git - lyx.git/blob - src/support/forkedcall.h
Collapse all those LFUN_XYZ_APPLY to a single LFUN_INSET_APPLY.
[lyx.git] / src / support / forkedcall.h
1 // -*- C++ -*-
2 /**
3  *  \file forkedcall.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Asger Alstrup
8  *
9  * Interface cleaned up by
10  * \author Angus Leeming
11  *
12  * Full author contact details are available in file CREDITS
13  *
14  * An instance of Class Forkedcall represents a single child process.
15  *
16  * Class Forkedcall uses fork() and execvp() to lauch the child process.
17  *
18  * Once launched, control is returned immediately to the parent process
19  * but a Signal can be emitted upon completion of the child.
20  *
21  * The child process is not killed when the Forkedcall instance goes out of
22  * scope, but it can be killed by an explicit invocation of the kill() member
23  * function.
24  */
25
26 #ifndef FORKEDCALL_H
27 #define FORKEDCALL_H
28
29 #include "LString.h"
30
31 #include <boost/shared_ptr.hpp>
32 #include <boost/signals/signal2.hpp>
33 #include <boost/function/function0.hpp>
34
35 #include <sys/types.h>
36
37 class ForkedProcess {
38 public:
39         ///
40         enum Starttype {
41                 ///
42                 Wait,
43                 ///
44                 DontWait
45         };
46
47         ///
48         ForkedProcess();
49         ///
50         virtual ~ForkedProcess() {}
51         ///
52         virtual ForkedProcess * clone() const = 0;
53
54         /** A SignalType signal is can be emitted once the forked process
55          *  has finished. It passes:
56          *  the PID of the child and;
57          *  the return value from the child.
58          *
59          *  We use a signal rather than simply a callback function so that
60          *  we can return easily to C++ methods, rather than just globally
61          *  accessible functions.
62          */
63         typedef boost::signal2<void, pid_t, int> SignalType;
64
65         /** The signal is connected in the calling routine to the desired
66          *  slot. We pass a shared_ptr rather than a reference to the signal
67          *  because it is eminently possible for the instance of the calling
68          *  class (and hence the signal) to be destructed before the forked
69          *  call is complete.
70          *
71          *  It doesn't matter if the slot disappears, SigC takes care of that.
72          */
73         typedef boost::shared_ptr<SignalType> SignalTypePtr;
74
75         /** Invoking the following methods makes sense only if the command
76          *  is running asynchronously!
77          */
78
79         /** gets the PID of the child process.
80          *  Used by the timer.
81          */
82         pid_t pid() const { return pid_; }
83
84         /** Emit the signal.
85          *  Used by the timer.
86          */
87         void emitSignal();
88
89         /** Set the return value of the child process.
90          *  Used by the timer.
91          */
92         void setRetValue(int r) { retval_ = r; }
93
94         /// Returns the identifying command (for display in the GUI perhaps).
95         string const & command() const { return command_; }
96
97         /// is the process running ?
98         bool running() const;
99
100         /** Kill child prematurely.
101          *  First, a SIGHUP is sent to the child.
102          *  If that does not end the child process within "tolerance"
103          *  seconds, the SIGKILL signal is sent to the child.
104          *  When the child is dead, the callback is called.
105          */
106         void kill(int tolerance = 5);
107
108 protected:
109         /** Wait for child process to finish.
110          *  Returns returncode from child.
111          */
112         int runBlocking();
113         /** Do not wait for child process to finish.
114          *  Returns returncode from child.
115          */
116         int runNonBlocking();
117
118         /// Callback function
119         SignalTypePtr signal_;
120
121         /// identifying command (for display in the GUI perhaps).
122         string command_;
123
124         /// Process ID of child
125         pid_t pid_;
126
127         /// Return value from child
128         int retval_;
129 private:
130         /// generate child in background
131         virtual int generateChild() = 0;
132
133         /// Wait for child process to finish. Updates returncode from child.
134         int waitForChild();
135 };
136
137
138 class Forkedcall : public ForkedProcess {
139 public:
140         ///
141         virtual ForkedProcess * clone() const {
142                 return new Forkedcall(*this);
143         }
144
145         /** Start the child process.
146          *
147          *  The command "what" is passed to execvp() for execution.
148          *
149          *  There are two startscript commands available. They differ in that
150          *  the second receives a signal that is executed on completion of
151          *  the command. This makes sense only for a command executed
152          *  in the background, ie DontWait.
153          *
154          *  The other startscript command can be executed either blocking
155          *  or non-blocking, but no signal will be emitted on finishing.
156          */
157         int startscript(Starttype, string const & what);
158
159         ///
160         int startscript(string const & what, SignalTypePtr);
161
162 private:
163         ///
164         virtual int generateChild();
165 };
166
167 #endif // FORKEDCALL_H