At least I find it a bit nicer. Comments/Objections?

I have not fixed up qt and gtk to use the same scheme yet.

(And I you wonder what I am doing: I am combing my way through the
code and looking close at stuff that went in when I was not paying
close attention. And trying to understand all the cryptic stuff that
Andre added of course.)

Index: lyxsocket.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxsocket.C,v
retrieving revision 1.4
diff -u -p -r1.4 lyxsocket.C
--- lyxsocket.C	5 Nov 2003 10:49:07 -0000	1.4
+++ lyxsocket.C	18 Jul 2004 02:57:47 -0000
@@ -24,9 +24,11 @@
 #include "support/lyxlib.h"
 #include "support/socktools.h"
 
-#include <iostream>
+#include <boost/bind.hpp>
+
 #include <cerrno>
 
+using boost::shared_ptr;
 
 using std::auto_ptr;
 using std::endl;
@@ -38,7 +40,7 @@ using std::string;
 // that can connect at the same time.
 LyXServerSocket::LyXServerSocket(LyXFunc * f, string const & addr)
 	: func(f),
-	  fd_(lyx::support::socktools::listen(addr, MAX_CLIENTS)),
+	  fd_(lyx::support::socktools::listen(addr, 3)),
 	  address_(addr)
 {
 	if (fd_ == -1) {
@@ -52,7 +54,11 @@ LyXServerSocket::LyXServerSocket(LyXFunc
 	// Needed by lyxclient
 	lyx::support::putenv("LYXSOCKET", address_);
 
-	lyx_gui::set_serversocket_callback(this);
+	lyx_gui::register_socket_callback(
+		fd_,
+		boost::bind(&LyXServerSocket::serverCallback, *this)
+		);
+
 	lyxerr[Debug::LYXSERVER] << "lyx: New server socket "
 				 << fd_ << ' ' << address_ << endl;
 }
@@ -61,22 +67,16 @@ LyXServerSocket::LyXServerSocket(LyXFunc
 // Close the socket and remove the address of the filesystem.
 LyXServerSocket::~LyXServerSocket()
 {
+	lyx_gui::unregister_socket_callback(fd_);
 	::close(fd_);
 	lyx::support::unlink(address_);
-	while (!clients.empty()) close(*clients.rbegin());
 	lyxerr[Debug::LYXSERVER] << "lyx: Server socket quitting" << endl;
 }
 
 
-int LyXServerSocket::fd() const
-{
-	return fd_;
-}
-
-
 string const & LyXServerSocket::address() const
 {
-	return address_;
+ 	return address_;
 }
 
 
@@ -84,23 +84,36 @@ string const & LyXServerSocket::address(
 // is OK and if the number of clients does not exceed MAX_CLIENTS
 void LyXServerSocket::serverCallback()
 {
-	auto_ptr<LyXDataSocket> client(new LyXDataSocket(this));
-	if (client->connected()) {
-		if (clients.size() == MAX_CLIENTS) {
-			client->writeln("BYE:Too many clients connected");
-		} else {
-			lyx_gui::set_datasocket_callback(client.get());
-			clients.insert(client.release());
-			return;
-		}
+	int const client_fd = lyx::support::socktools::accept(fd_);
+
+	if (fd_ == -1) {
+		lyxerr[Debug::LYXSERVER] << "lyx: Failed to accept new client"
+					 << endl;
+		return;
 	}
+
+	if (clients.size() >= MAX_CLIENTS) {
+		writeln("BYE:Too many clients connected");
+		return;
+	}
+
+	// Register the new client.
+	clients[client_fd] =
+		shared_ptr<LyXDataSocket>(new LyXDataSocket(client_fd));
+	lyx_gui::register_socket_callback(
+		client_fd,
+		boost::bind(&LyXServerSocket::dataCallback,
+			    *this, client_fd)
+		);
 }
 
 
 // Reads and processes input from client and check
 // if the connection has been closed
-void LyXServerSocket::dataCallback(LyXDataSocket * client)
+void LyXServerSocket::dataCallback(int fd)
 {
+	shared_ptr<LyXDataSocket> client = clients[fd];
+
 	string line;
 	string::size_type pos;
 	bool saidbye = false;
@@ -133,17 +146,30 @@ void LyXServerSocket::dataCallback(LyXDa
 	}
 
 	if (saidbye || (!client->connected())) {
-		close(client);
+		clients.erase(fd);
 	}
 }
 
 
-// Removes client callback and deletes client object
-void LyXServerSocket::close(LyXDataSocket * client)
+void LyXServerSocket::writeln(string const & line)
 {
-	lyx_gui::remove_datasocket_callback(client);
-	clients.erase(client);
-	delete client;
+	string const linen(line + '\n');
+	int const size = linen.size();
+	int const written = ::write(fd_, linen.c_str(), size);
+	if (written < size) { // Allways mean end of connection.
+		if ((written == -1) && (errno == EPIPE)) {
+			// The program will also receive a SIGPIPE
+			// that must be catched
+			lyxerr << "lyx: Server socket " << fd_
+			       << " connection closed while writing." << endl;
+		} else {
+			// Anything else, including errno == EAGAIN, must be
+			// considered IO error. EAGAIN should never happen
+			// when line is small
+			lyxerr << "lyx: Server socket " << fd_
+			     << " IO error: " << strerror(errno);
+		}
+	}
 }
 
 // Debug
@@ -152,44 +178,27 @@ void LyXServerSocket::close(LyXDataSocke
 //	lyxerr << "LyXServerSocket debug dump.\n"
 //	     << "fd = " << fd_ << ", address = " << address_ << ".\n"
 //	     << "Clients: " << clients.size() << ".\n";
-//	if (!clients.empty()) {
-//		std::set<LyXDataSocket *>::const_iterator client = clients.begin();
-//		std::set<LyXDataSocket *>::const_iterator end = clients.end();
-//		for (; client != end; ++client)
-//			lyxerr << "fd = " << (*client)->fd() << "\n";
-//	}
+//	std::map<int, shared_ptr<LyXDataSocket> >::const_iterator client = clients.begin();
+//	std::map<int, shared_ptr<LyXDataSocket> >::const_iterator end = clients.end();
+//	for (; client != end; ++client)
+//		lyxerr << "fd = " << client->first << '\n';
 // }
 
 
-LyXDataSocket::LyXDataSocket(LyXServerSocket * serv)
-	:server_(serv),
-	 fd_(lyx::support::socktools::accept(serv->fd()))
+LyXDataSocket::LyXDataSocket(int fd)
+	: fd_(fd), connected_(true)
 {
-	if (fd_ == -1) {
-		connected_ = false;
-	} else {
-		lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
-		connected_ = true;
-	}
+	lyxerr[Debug::LYXSERVER] << "lyx: New data socket " << fd_ << endl;
 }
 
 
 LyXDataSocket::~LyXDataSocket()
 {
 	::close(fd_);
-	lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting." << endl;
-}
 
-
-LyXServerSocket * LyXDataSocket::server() const
-{
-	return server_;
-}
-
-
-int LyXDataSocket::fd() const
-{
-	return fd_;
+	lyx_gui::unregister_socket_callback(fd_);
+	lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_ << " quitting."
+				 << endl;
 }
 
 
@@ -205,12 +214,10 @@ bool LyXDataSocket::readln(string & line
 	int const charbuf_size = 100;
         char charbuf[charbuf_size]; // buffer for the ::read() system call
 	int count;
-	string::size_type pos;
 
 	// read and store characters in buffer
 	while ((count = ::read(fd_, charbuf, charbuf_size - 1)) > 0) {
-		charbuf[count] = '\0'; // turn it into a c string
-		buffer += charbuf;
+		buffer_.append(charbuf, charbuf + count);
 	}
 
 	// Error conditions. The buffer must still be
@@ -226,13 +233,14 @@ bool LyXDataSocket::readln(string & line
 	}
 
 	// Cut a line from buffer
-	if ((pos = buffer.find('\n')) == string::npos) {
+	string::size_type pos = buffer_.find('\n');
+	if (pos == string::npos) {
 		lyxerr[Debug::LYXSERVER] << "lyx: Data socket " << fd_
 					 << ": line not completed." << endl;
 		return false; // No complete line stored
 	}
-	line = buffer.substr(0, pos);
-	buffer = buffer.substr(pos + 1);
+	line = buffer_.substr(0, pos);
+	buffer_.erase(0, pos + 1);
 	return true;
 }
 
@@ -240,9 +248,9 @@ bool LyXDataSocket::readln(string & line
 // Write a line of the form <key>:<value> to the socket
 void LyXDataSocket::writeln(string const & line)
 {
-	string linen(line + '\n');
-	int size = linen.size();
-	int written = ::write(fd_, linen.c_str(), size);
+	string const linen(line + '\n');
+	int const size = linen.size();
+	int const written = ::write(fd_, linen.c_str(), size);
 	if (written < size) { // Allways mean end of connection.
 		if ((written == -1) && (errno == EPIPE)) {
 			// The program will also receive a SIGPIPE
Index: lyxsocket.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/lyxsocket.h,v
retrieving revision 1.2
diff -u -p -r1.2 lyxsocket.h
--- lyxsocket.h	3 Apr 2004 08:36:59 -0000	1.2
+++ lyxsocket.h	18 Jul 2004 02:57:47 -0000
@@ -17,12 +17,15 @@
 #include "support/socktools.h"
 #include "lyxfunc.h"
 
+#include <boost/shared_ptr.hpp>
+
 #include <string>
-#include <set>
+#include <map>
 
 class LyXServerSocket;
 class LyXDataSocket;
 
+
 /** Sockets can be in two states: listening and connected.
  *  Connected sockets are used to transfer data, and will therefore
  *  be called Data Sockets. Listening sockets are used to create
@@ -32,24 +35,22 @@ class LyXDataSocket;
  * This class encapsulates local (unix) server socket operations and
  * manages LyXDataSockets objects that are created when clients connect.
  */
-class LyXServerSocket
-{
+class LyXServerSocket {
 public:
+	///
 	LyXServerSocket(LyXFunc *, std::string const &);
+	///
 	~LyXServerSocket();
-	/// File descriptor of the socket
-	int fd() const;
 	/// Address of the local socket
 	std::string const & address() const;
 	/// To be called when there is activity in the server socket
 	void serverCallback();
 	/// To be called when there is activity in the data socket
-	void dataCallback(LyXDataSocket *);
-
+	void dataCallback(int fd);
 private:
-	/// Close the connection to the argument client
-	void close(LyXDataSocket *);
-
+	///
+	void writeln(std::string const &);
+	///
 	LyXFunc * func;
 	/// File descriptor for the server socket
 	int fd_;
@@ -60,37 +61,32 @@ private:
                 MAX_CLIENTS = 10
         };
 	/// All connections
-	std::set<LyXDataSocket *> clients;
+	std::map<int, boost::shared_ptr<LyXDataSocket> > clients;
 };
 
 
 /** This class encapsulates data socket operations.
  *  It provides read and write IO operations on the socket.
  */
-class LyXDataSocket
-{
+class LyXDataSocket {
 public:
-	LyXDataSocket(LyXServerSocket *);
+	///
+	LyXDataSocket(int fd);
+	///
 	~LyXDataSocket();
-	/// The object that allocated us
-	LyXServerSocket * server() const;
-	/// File descriptor of the connection
-	int fd() const;
 	/// Connection status
 	bool connected() const;
 	/// Line buffered input from the socket
 	bool readln(std::string &);
 	/// Write the string + '\n' to the socket
 	void writeln(std::string const &);
-
 private:
-	LyXServerSocket * server_;
 	/// File descriptor for the data socket
 	int fd_;
 	/// True if the connection is up
 	bool connected_;
 	/// buffer for input data
-	std::string buffer;
+	std::string buffer_;
 };
 
 #endif // LYXSOCKET_H
Index: frontends/lyx_gui.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/lyx_gui.h,v
retrieving revision 1.24
diff -u -p -r1.24 lyx_gui.h
--- frontends/lyx_gui.h	13 Oct 2003 12:25:10 -0000	1.24
+++ frontends/lyx_gui.h	18 Jul 2004 02:57:47 -0000
@@ -15,6 +15,8 @@
 
 #include "FuncStatus.h"
 
+#include <boost/function.hpp>
+
 #include <string>
 #include <vector>
 
@@ -98,6 +100,7 @@ bool font_available(LyXFont const & font
 void set_read_callback(int fd, LyXComm * comm);
 void set_datasocket_callback(LyXDataSocket *);
 void set_serversocket_callback(LyXServerSocket *);
+void register_socket_callback(int fd, boost::function<void()> func);
 
 /**
  * remove a I/O read callback
@@ -106,6 +109,7 @@ void set_serversocket_callback(LyXServer
 void remove_read_callback(int fd);
 void remove_datasocket_callback(LyXDataSocket *);
 void remove_serversocket_callback(LyXServerSocket *);
+void unregister_socket_callback(int fd);
 
 } // namespace lyx_gui
 
Index: frontends/xforms/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/lyx_gui.C,v
retrieving revision 1.59
diff -u -p -r1.59 lyx_gui.C
--- frontends/xforms/lyx_gui.C	19 May 2004 15:11:37 -0000	1.59
+++ frontends/xforms/lyx_gui.C	18 Jul 2004 02:57:47 -0000
@@ -291,27 +291,26 @@ void start(string const & batch, vector<
 	lyxerr[Debug::GUI] << "Creating view: " << width << 'x' << height
 			   << '+' << xpos << '+' << ypos << endl;
 
-	boost::shared_ptr<XFormsView> view_ptr(new XFormsView(width, height));
-	LyX::ref().addLyXView(view_ptr);
+	boost::shared_ptr<XFormsView> view(new XFormsView(width, height));
+	LyX::ref().addLyXView(view);
 
-	XFormsView & view = *view_ptr.get();
-	view.show(xpos, ypos, "LyX");
-	view.init();
+	view->show(xpos, ypos, "LyX");
+	view->init();
 
 	// FIXME: some code below needs moving
 
-	lyxserver = new LyXServer(&view.getLyXFunc(), lyxrc.lyxpipes);
-	lyxsocket = new LyXServerSocket(&view.getLyXFunc(),
+	lyxserver = new LyXServer(&view->getLyXFunc(), lyxrc.lyxpipes);
+	lyxsocket = new LyXServerSocket(&view->getLyXFunc(),
 			  os::slashify_path(os::getTmpDir() + "/lyxsocket"));
 
 	vector<string>::const_iterator cit = files.begin();
 	vector<string>::const_iterator end = files.end();
 	for (; cit != end; ++cit)
-		view.view()->loadLyXFile(*cit, true);
+		view->view()->loadLyXFile(*cit, true);
 
 	// handle the batch commands the user asked for
 	if (!batch.empty())
-		view.getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
+		view->getLyXFunc().dispatch(lyxaction.lookupFunc(batch));
 
 	// enter the event loop
 	while (!finished) {
@@ -398,21 +397,8 @@ void C_read_callback(int, void * data)
 	comm->read_ready();
 }
 
-extern "C"
-void C_datasocket_callback(int, void * data)
-{
-	LyXDataSocket * client = static_cast<LyXDataSocket *>(data);
-	client->server()->dataCallback(client);
 }
 
-extern "C"
-void C_serversocket_callback(int, void * data)
-{
-	LyXServerSocket * server = static_cast<LyXServerSocket *>(data);
-	server->serverCallback();
-}
-
-}
 
 void set_read_callback(int fd, LyXComm * comm)
 {
@@ -424,25 +410,34 @@ void remove_read_callback(int fd)
 	fl_remove_io_callback(fd, FL_READ, C_read_callback);
 }
 
-void set_datasocket_callback(LyXDataSocket * p)
-{
-	fl_add_io_callback(p->fd(), FL_READ, C_datasocket_callback, p);
-}
 
-void remove_datasocket_callback(LyXDataSocket * p)
+namespace {
+
+std::map<int, boost::function<void()> > socket_callbacks;
+
+extern "C"
+void C_socket_callback(int fd, void *)
 {
-	fl_remove_io_callback(p->fd(), FL_READ, C_datasocket_callback);
+	socket_callbacks[fd]();
 }
 
-void set_serversocket_callback(LyXServerSocket * p)
+
+} // NS anon
+
+
+void register_socket_callback(int fd, boost::function<void()> func)
 {
-	fl_add_io_callback(p->fd(), FL_READ, C_serversocket_callback, p);
+	socket_callbacks[fd] = func;
+	fl_add_io_callback(fd, FL_READ, C_socket_callback, 0);
 }
 
-void remove_serversocket_callback(LyXServerSocket * p)
+
+void unregister_socket_callback(int fd)
 {
-	fl_remove_io_callback(p->fd(), FL_READ, C_serversocket_callback);
+	fl_remove_io_callback(fd, FL_READ, C_socket_callback);
+	socket_callbacks.erase(fd);
 }
+
 
 string const roman_font_name()
 {
-- 
        Lgb

Reply via email to