]> git.lyx.org Git - lyx.git/blobdiff - src/support/ForkedCalls.h
Fix bug #4269
[lyx.git] / src / support / ForkedCalls.h
index 7d26bf42f3202c10dae128e8240c92a049457954..8a4bf1d4aa40a9cc53a4e904fd73ff464eab4cbc 100644 (file)
 #ifndef FORKEDCALLS_H
 #define FORKEDCALLS_H
 
-#include <boost/shared_ptr.hpp>
-#include <boost/signal.hpp>
+#include "support/signals.h"
+#include "support/strfwd.h"
 
 #ifdef HAVE_SYS_TYPES_H
 # include <sys/types.h>
 #endif
 
-#include <list>
-#include <queue>
-#include <string>
-#include <utility>
-#include <vector>
+#include <memory>
 
 
 namespace lyx {
@@ -46,9 +42,9 @@ public:
        ///
        virtual ~ForkedProcess() {}
        ///
-       virtual boost::shared_ptr<ForkedProcess> clone() const = 0;
+       virtual std::shared_ptr<ForkedProcess> clone() const = 0;
 
-       /** A SignalType signal is can be emitted once the forked process
+       /** A Signal signal can be emitted once the forked process
         *  has finished. It passes:
         *  the PID of the child and;
         *  the return value from the child.
@@ -57,7 +53,8 @@ public:
         *  we can return easily to C++ methods, rather than just globally
         *  accessible functions.
         */
-       typedef boost::signal<void(pid_t, int)> SignalType;
+       typedef signals2::signal<void(pid_t, int)> sig;
+       typedef sig::slot_type slot;
 
        /** The signal is connected in the calling routine to the desired
         *  slot. We pass a shared_ptr rather than a reference to the signal
@@ -65,9 +62,10 @@ public:
         *  class (and hence the signal) to be destructed before the forked
         *  call is complete.
         *
-        *  It doesn't matter if the slot disappears, SigC takes care of that.
+        *  Use Slot::track or Signal::scoped_connection to ensure that the
+        *  connection is closed before the slot expires.
         */
-       typedef boost::shared_ptr<SignalType> SignalTypePtr;
+       typedef std::shared_ptr<sig> sigPtr;
 
        /** Invoking the following methods makes sense only if the command
         *  is running asynchronously!
@@ -102,14 +100,23 @@ public:
         */
        void kill(int tolerance = 5);
 
+       /// Returns true if this is a child process
+       static bool iAmAChild() { return IAmAChild; }
+
 protected:
        /** Spawn the child process.
         *  Returns returncode from child.
         */
        int run(Starttype type);
 
+       /// implement our own version of fork()
+       /// it just returns -1 if ::fork() is not defined
+       /// otherwise, it forks and sets the global child-process
+       /// boolean IAmAChild
+       pid_t fork();
+
        /// Callback function
-       SignalTypePtr signal_;
+       sigPtr signal_;
 
        /// identifying command (for display in the GUI perhaps).
        std::string command_;
@@ -123,12 +130,15 @@ private:
        /// generate child in background
        virtual int generateChild() = 0;
 
+       ///
+       static bool IAmAChild;
+
        /// Wait for child process to finish. Updates returncode from child.
        int waitForChild();
 };
 
 
-/* 
+/**
  * An instance of class ForkedCall represents a single child process.
  *
  * Class ForkedCall uses fork() and execvp() to lauch the child process.
@@ -144,13 +154,17 @@ private:
 class ForkedCall : public ForkedProcess {
 public:
        ///
-       virtual boost::shared_ptr<ForkedProcess> clone() const {
-               return boost::shared_ptr<ForkedProcess>(new ForkedCall(*this));
+       ForkedCall(std::string const & path = empty_string(),
+                  std::string const & lpath = empty_string());
+       ///
+       virtual std::shared_ptr<ForkedProcess> clone() const {
+               return std::make_shared<ForkedCall>(*this);
        }
 
        /** Start the child process.
         *
-        *  The command "what" is passed to execvp() for execution.
+        *  The command "what" is passed to execvp() for execution. "$$s" is
+        *  replaced accordingly by commandPrep().
         *
         *  There are two startScript commands available. They differ in that
         *  the second receives a signal that is executed on completion of
@@ -163,96 +177,55 @@ public:
        int startScript(Starttype, std::string const & what);
 
        ///
-       int startScript(std::string const & what, SignalTypePtr);
+       int startScript(std::string const & what, sigPtr ptr);
 
 private:
        ///
        virtual int generateChild();
+       ///
+       std::string cmd_prefix_;
 };
 
 
 /**
- * This class implements a queue of forked processes. In order not to
+ * This interfaces a queue of forked processes. In order not to
  * hose the system with multiple processes running simultaneously, you can
  * request the addition of your process to this queue and it will be
  * executed when its turn comes.
  *
  */
 
-class ForkedCallQueue {
-public:
-       /// A process in the queue
-       typedef std::pair<std::string, ForkedCall::SignalTypePtr> Process;
-       /** Add a process to the queue. Processes are forked sequentially
-        *  only one is running at a time.
-        *  Connect to the returned signal and you'll be informed when
-        *  the process has ended.
-        */
-       ForkedCall::SignalTypePtr add(std::string const & process);
-       /// Query whether the queue is running a forked process now.
-       bool running() const;
-       /// Get the and only instance of the class
-       static ForkedCallQueue & get();
+namespace ForkedCallQueue {
 
-private:
-       /** this class is a singleton class... use
-        *  ForkedCallQueue::get() instead
-        */
-       ForkedCallQueue();
-       /// in-progress queue
-       std::queue<Process> callQueue_;
-       ///
-       bool running_;
-       ///
-       void callNext();
-       ///
-       void startCaller();
-       ///
-       void stopCaller();
-       ///
-       void callback(pid_t, int);
-};
+ForkedCall::sigPtr add(std::string const & process);
+/// Query whether the queue is running a forked process now.
+bool running();
+
+} // namespace ForkedCallQueue
 
 
 /**
- * A class for the control of child processes launched using
- * fork() and execvp().
+ * Control of child processes launched using fork() and execvp().
  */
 
-class ForkedCallsController {
-public:
-       /// Get hold of the only controller that can exist inside the process.
-       static ForkedCallsController & get();
-
-       /// Add a new child process to the list of controlled processes.
-       void addCall(ForkedProcess const &);
-
-       /** Those child processes that are found to have finished are removed
-        *  from the list and their callback function is passed the final
-        *  return state.
-        */
-       void handleCompletedProcesses();
-
-       /** Kill this process prematurely and remove it from the list.
-        *  The process is killed within tolerance secs.
-        *  See forkedcall.[Ch] for details.
-        */
-       void kill(pid_t, int tolerance = 5);
+namespace ForkedCallsController {
 
-private:
-       ForkedCallsController();
-       ForkedCallsController(ForkedCallsController const &);
-       ~ForkedCallsController();
+/// Add a new child process to the list of controlled processes.
+void addCall(ForkedProcess const &);
 
-       typedef boost::shared_ptr<ForkedProcess> ForkedProcessPtr;
-       typedef std::list<ForkedProcessPtr> ListType;
-       typedef ListType::iterator iterator;
+/** Those child processes that are found to have finished are removed
+ *  from the list and their callback function is passed the final
+ *  return state.
+ */
+void handleCompletedProcesses();
 
-       iterator find_pid(pid_t);
+/** Kill this process prematurely and remove it from the list.
+ *  The process is killed within tolerance secs.
+ *  See forkedcall.[Ch] for details.
+ */
+void kill(pid_t, int tolerance = 5);
 
-       /// The child processes
-       ListType forkedCalls;
-};
+} // namespace ForkedCallsController
 
 
 #if defined(_WIN32)