]> git.lyx.org Git - lyx.git/blob - src/support/forkedcall.h
MSVC build fixes.
[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 <boost/shared_ptr.hpp>
30 #include <boost/signal.hpp>
31
32 #include <sys/types.h>
33
34 // pid_t isn't defined by the stdlibs that ship with MSVC.
35 #if defined (_WIN32) && defined(_MSC_VER)
36 typedef int pid_t;
37 #endif
38
39
40 namespace lyx {
41 namespace support {
42
43 class ForkedProcess {
44 public:
45         ///
46         enum Starttype {
47                 ///
48                 Wait,
49                 ///
50                 DontWait
51         };
52
53         ///
54         ForkedProcess();
55         ///
56         virtual ~ForkedProcess() {}
57         ///
58         virtual boost::shared_ptr<ForkedProcess> clone() const = 0;
59
60         /** A SignalType signal is can be emitted once the forked process
61          *  has finished. It passes:
62          *  the PID of the child and;
63          *  the return value from the child.
64          *
65          *  We use a signal rather than simply a callback function so that
66          *  we can return easily to C++ methods, rather than just globally
67          *  accessible functions.
68          */
69         typedef boost::signal<void(pid_t, int)> SignalType;
70
71         /** The signal is connected in the calling routine to the desired
72          *  slot. We pass a shared_ptr rather than a reference to the signal
73          *  because it is eminently possible for the instance of the calling
74          *  class (and hence the signal) to be destructed before the forked
75          *  call is complete.
76          *
77          *  It doesn't matter if the slot disappears, SigC takes care of that.
78          */
79         typedef boost::shared_ptr<SignalType> SignalTypePtr;
80
81         /** Invoking the following methods makes sense only if the command
82          *  is running asynchronously!
83          */
84
85         /** gets the PID of the child process.
86          *  Used by the timer.
87          */
88         pid_t pid() const { return pid_; }
89
90         /** Emit the signal.
91          *  Used by the timer.
92          */
93         void emitSignal();
94
95         /** Set the return value of the child process.
96          *  Used by the timer.
97          */
98         void setRetValue(int r) { retval_ = r; }
99
100         /// Returns the identifying command (for display in the GUI perhaps).
101         std::string const & command() const { return command_; }
102
103         /// is the process running ?
104         bool running() const;
105
106         /** Kill child prematurely.
107          *  First, a SIGHUP is sent to the child.
108          *  If that does not end the child process within "tolerance"
109          *  seconds, the SIGKILL signal is sent to the child.
110          *  When the child is dead, the callback is called.
111          */
112         void kill(int tolerance = 5);
113
114 protected:
115         /** Spawn the child process.
116          *  Returns returncode from child.
117          */
118         int run(Starttype type);
119
120         /// Callback function
121         SignalTypePtr signal_;
122
123         /// identifying command (for display in the GUI perhaps).
124         std::string command_;
125
126         /// Process ID of child
127         pid_t pid_;
128
129         /// Return value from child
130         int retval_;
131 private:
132         /// generate child in background
133         virtual int generateChild() = 0;
134
135         /// Wait for child process to finish. Updates returncode from child.
136         int waitForChild();
137 };
138
139
140 class Forkedcall : public ForkedProcess {
141 public:
142         ///
143         virtual boost::shared_ptr<ForkedProcess> clone() const {
144                 return boost::shared_ptr<ForkedProcess>(new Forkedcall(*this));
145         }
146
147         /** Start the child process.
148          *
149          *  The command "what" is passed to execvp() for execution.
150          *
151          *  There are two startscript commands available. They differ in that
152          *  the second receives a signal that is executed on completion of
153          *  the command. This makes sense only for a command executed
154          *  in the background, ie DontWait.
155          *
156          *  The other startscript command can be executed either blocking
157          *  or non-blocking, but no signal will be emitted on finishing.
158          */
159         int startscript(Starttype, std::string const & what);
160
161         ///
162         int startscript(std::string const & what, SignalTypePtr);
163
164 private:
165         ///
166         virtual int generateChild();
167 };
168
169 } // namespace support
170 } // namespace lyx
171
172 #endif // FORKEDCALL_H