X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2FServer.h;h=40021daa414c14bf82f15b36bc2ab1c60f48e3e5;hb=7920a12065458b4106d893cafd41afc53efd1b3c;hp=fb7cd4feed9893e0307fe881af659a5a20213680;hpb=d079c908b371284bfb32f1c3f60781f34a99b3e5;p=lyx.git diff --git a/src/Server.h b/src/Server.h index fb7cd4feed..40021daa41 100644 --- a/src/Server.h +++ b/src/Server.h @@ -4,8 +4,9 @@ * This file is part of LyX, the document processor. * Licence details can be found in the file COPYING. * - * \author Lars Gullik Bjønnes + * \author Lars Gullik Bjønnes * \author Jean-Marc Lasgouttes + * \author Enrico Forestieri * * Full author contact details are available in file CREDITS. */ @@ -13,23 +14,69 @@ #ifndef SERVER_H #define SERVER_H -#include +#include "support/signals.h" + +#include + +#ifdef _WIN32 +#include +#include +#include +#endif namespace lyx { -class LyXFunc; class Server; -/** This class managed the pipes used for communicating with clients. +/** This class manages the pipes used for communicating with clients. Usage: Initialize with pipe-filename-base, client class to receive messages, and callback-function that will be called with the messages. When you want to send, use "send()". This class encapsulates all the dirty communication and thus provides a clean string interface. */ -class LyXComm : public boost::signals::trackable { +#ifndef _WIN32 +class LyXComm { +#else +class LyXComm : public QObject { + Q_OBJECT + + friend DWORD WINAPI pipeServerWrapper(void *); + +public: + /// Max number of clients + enum { MAX_CLIENTS = 10 }; + +private: + /// Max number of pipe instances + enum { MAX_PIPES = 2 * MAX_CLIENTS }; + + /// I/O buffer size + enum { PIPE_BUFSIZE = 512 }; + + /// Pipe client time-out + enum { PIPE_TIMEOUT = 5000 }; + + /// Pipe states + enum PipeState { + CONNECTING_STATE, + READING_STATE, + WRITING_STATE + }; + + /// Pipe instances + typedef struct { + OVERLAPPED overlap; + HANDLE handle; + std::string iobuf; + char readbuf[PIPE_BUFSIZE]; + DWORD nbytes; + PipeState state; + bool pending_io; + } PipeInst; +#endif public: /** When we receive a message, we send it to a client. This is one of the small things that would have been a lot @@ -38,12 +85,7 @@ public: typedef void (*ClientCallbackfct)(Server *, std::string const &); /// Construct with pipe-basename and callback to receive messages - LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0) - : pipename(pip), client(cli), clientcb(ccb) - { - ready = false; - openConnection(); - } + LyXComm(std::string const & pip, Server * cli, ClientCallbackfct ccb = 0); /// ~LyXComm() { closeConnection(); } @@ -55,7 +97,14 @@ public: void send(std::string const &); /// asynch ready-to-be-read notification +#ifndef _WIN32 void read_ready(); +#else + void read_ready(DWORD); +#endif + + /// Tell whether we asked another instance of LyX to open the files + bool deferredLoading() { return deferred_loading_; } private: /// the filename of the in pipe @@ -70,6 +119,10 @@ private: /// Close pipes void closeConnection(); + /// Load files in another running instance of LyX + bool loadFilesInOtherInstance(); + +#ifndef _WIN32 /// start a pipe int startPipe(std::string const &, bool); @@ -77,24 +130,69 @@ private: void endPipe(int &, std::string const &, bool); /// This is -1 if not open - int infd; + int infd_; /// This is -1 if not open - int outfd; + int outfd_; +#else + /// The pipe server returns false when exiting due to an error + bool pipeServer(); + + /// Start an overlapped connection + bool startPipe(DWORD); + + /// Reset an overlapped connection + bool resetPipe(DWORD, bool close_handle = false); + + /// Close event and pipe handles + void closeHandles(); + + /// Catch pipe ready-to-be-read notification + bool event(QEvent *); + + /// Check whether the pipe server must be stopped + bool checkStopServer(DWORD timeout = 0); + + /// The filename of a (in or out) pipe instance + std::string const pipeName(DWORD) const; + + /// Pipe instances + PipeInst pipe_[MAX_PIPES]; + + /// Pipe server control events + HANDLE event_[MAX_PIPES + 1]; + + /// Reply buffer + std::string outbuf_; + + /// Synchronize access to outbuf_ + HANDLE outbuf_mutex_; + + /// Windows event for stopping the pipe server + HANDLE stopserver_; + + /// Pipe server thread handle + HANDLE server_thread_; +#endif /// Are we up and running? - bool ready; + bool ready_; /// Base of pipename including path - std::string pipename; + std::string pipename_; /// The client - Server * client; + Server * client_; /// The client callback function - ClientCallbackfct clientcb; -}; + ClientCallbackfct clientcb_; + /// Did we defer loading of files to another instance? + bool deferred_loading_; + + /// Track object's liveness + support::Trackable tracker_; +}; /// @@ -103,46 +201,46 @@ public: // FIXME IN 0.13 // Hack! This should be changed in 0.13 - // The lyx server should not take an argument "LyXFunc" but this is - // how it will be done for 0.12. In 0.13 we must write a non-gui - // bufferview. // IMO lyxserver is atypical, and for the moment the only one, non-gui // bufferview. We just have to find a way to handle situations like if // lyxserver is using a buffer that is being edited with a bufferview. // With a common buffer list this is not a problem, maybe. (Alejandro) /// - Server(LyXFunc * f, std::string const & pip) - : numclients(0), func(f), pipes(pip, (this), callback) {} + Server(std::string const & pip); /// ~Server(); /// void notifyClient(std::string const &); + /// + bool deferredLoadingToOtherInstance() { return pipes_.deferredLoading(); } /// whilst crashing etc. - void emergencyCleanup() { pipes.emergencyCleanup(); } + void emergencyCleanup() { pipes_.emergencyCleanup(); } + /// + void callback(std::string const & msg); private: - /// - static void callback(Server *, std::string const & msg); /// Names and number of current clients - enum { - /// - MAX_CLIENTS = 10 - }; - /// - std::string clients[MAX_CLIENTS]; +#ifndef _WIN32 + enum { MAX_CLIENTS = 10 }; +#else + enum { MAX_CLIENTS = LyXComm::MAX_CLIENTS }; +#endif /// - int numclients; + std::string clients_[MAX_CLIENTS]; /// - LyXFunc * func; + int numclients_; /// - LyXComm pipes; + LyXComm pipes_; }; /// Implementation is in LyX.cpp -extern Server & theServer(); +Server & theServer(); + +/// Implementation is in LyX.cpp +extern std::vector & theFilesToLoad(); } // namespace lyx -#endif // SERVER_H +#endif // SERVER_H