[EMAIL PROTECTED] (Lars Gullik Bj�nnes) writes:
| At least I find it a bit nicer. Comments/Objections?
>
| I have not fixed up qt and gtk to use the same scheme yet.
This patch supposedly fixes up qt and gtk as well. (I am not even
compiled it...)
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 03:37:49 -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: 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 03:37:49 -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,19 +67,13 @@ 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_;
@@ -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: 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 03:37:49 -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 03:37:49 -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()
{
Index: frontends/qt2/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/lyx_gui.C,v
retrieving revision 1.66
diff -u -p -r1.66 lyx_gui.C
--- frontends/qt2/lyx_gui.C 23 Jun 2004 14:04:09 -0000 1.66
+++ frontends/qt2/lyx_gui.C 18 Jul 2004 03:37:49 -0000
@@ -35,6 +35,7 @@
// All is well if the namespace is visible first.
#include <boost/signals/signal1.hpp>
#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
#include "QtView.h"
#include "io_callback.h"
@@ -57,6 +58,8 @@ using lyx::frontend::QtView;
namespace os = lyx::support::os;
+using boost::shared_ptr;
+
#ifndef CXX_GLOBAL_CSTD
using std::exit;
#endif
@@ -78,7 +81,7 @@ float getDPI()
}
map<int, io_callback *> io_callbacks;
-map<int, socket_callback *> socket_callbacks;
+map<int, shared_ptr<socket_callback> > socket_callbacks;
} // namespace anon
@@ -250,9 +253,9 @@ FuncStatus getStatus(FuncRequest const &
// application can still be accessed without giving focus to
// the main window. In this case, we want to disable the menu
// entries that are buffer-related.
- if (use_gui
+ if (use_gui
&& qApp->activeWindow() != qApp->mainWidget()
- && !lyxaction.funcHasFlag(ev.action, LyXAction::NoBuffer))
+ && !lyxaction.funcHasFlag(ev.action, LyXAction::NoBuffer))
flag.enabled(false);
#endif
@@ -301,34 +304,17 @@ void remove_read_callback(int fd)
}
-void set_datasocket_callback(LyXDataSocket * p)
+void register_socket_callback(int fd, boost::function<void()> func)
{
- socket_callbacks[p->fd()] = new socket_callback(p);
+ socket_callbacks[fd] = shared_ptr<socket_callback>(new socket_callback(fd, func));
}
-void set_serversocket_callback(LyXServerSocket * p)
-{
- socket_callbacks[p->fd()] = new socket_callback(p);
-}
-
-void remove_socket_callback(int fd)
-{
- map<int, socket_callback *>::iterator it = socket_callbacks.find(fd);
- if (it != socket_callbacks.end()) {
- delete it->second;
- socket_callbacks.erase(it);
- }
-}
-void remove_datasocket_callback(LyXDataSocket * p)
+void unregister_socket_callback(int fd)
{
- remove_socket_callback(p->fd());
+ socket_callbacks.erase(fd);
}
-void remove_serversocket_callback(LyXServerSocket * p)
-{
- remove_socket_callback(p->fd());
-}
string const roman_font_name()
{
Index: frontends/qt2/socket_callback.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/socket_callback.h,v
retrieving revision 1.2
diff -u -p -r1.2 socket_callback.h
--- frontends/qt2/socket_callback.h 12 Dec 2003 11:40:45 -0000 1.2
+++ frontends/qt2/socket_callback.h 18 Jul 2004 03:37:49 -0000
@@ -18,9 +18,8 @@
#include <qobject.h>
#include <qsocketnotifier.h>
#include <boost/scoped_ptr.hpp>
+#include <boost/function.hpp>
-class LyXServerSocket;
-class LyXDataSocket;
/**
* socket_callback - a simple wrapper for asynchronous socket notification
@@ -34,17 +33,14 @@ class socket_callback : public QObject {
Q_OBJECT
public:
/// connect a connection notification from the LyXServerSocket
- socket_callback(LyXServerSocket * server);
- socket_callback(LyXDataSocket * data);
+ socket_callback(int fd, boost::function<void()> func);
public slots:
- void server_received();
void data_received();
private:
/// our notifier
boost::scoped_ptr<QSocketNotifier> sn_;
-
- LyXServerSocket * server_;
- LyXDataSocket * data_;
+ /// The callback function
+ boost::function<void()> func_;
};
#endif // SOCKET_CALLBACK_H
Index: frontends/qt2/socket_callback.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/qt2/socket_callback.C,v
retrieving revision 1.3
diff -u -p -r1.3 socket_callback.C
--- frontends/qt2/socket_callback.C 20 May 2004 09:36:28 -0000 1.3
+++ frontends/qt2/socket_callback.C 18 Jul 2004 03:37:49 -0000
@@ -12,32 +12,17 @@
#include <config.h>
-#include "lyxsocket.h"
#include "socket_callback.h"
-socket_callback::socket_callback(LyXServerSocket * server)
- : server_(server)
+socket_callback::socket_callback(int fd, boost::function<void()> func)
+ : func_(func)
{
- sn_.reset(new QSocketNotifier(server->fd(), QSocketNotifier::Read, this));
- connect(sn_.get(), SIGNAL(activated(int)), this, SLOT(server_received()));
-}
-
-socket_callback::socket_callback(LyXDataSocket * data)
- : data_(data)
-{
- sn_.reset(new QSocketNotifier(data->fd(), QSocketNotifier::Read, this));
+ sn_.reset(new QSocketNotifier(fd, QSocketNotifier::Read, this));
connect(sn_.get(), SIGNAL(activated(int)), this, SLOT(data_received()));
}
-
-void socket_callback::server_received()
-{
- server_->serverCallback();
-}
-
-
-void socket_callback::data_received()
+void socket_callback::date_received()
{
- data_->server()->dataCallback(data_);
+ func_();
}
Index: frontends/gtk/lyx_gui.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/gtk/lyx_gui.C,v
retrieving revision 1.15
diff -u -p -r1.15 lyx_gui.C
--- frontends/gtk/lyx_gui.C 19 May 2004 15:11:32 -0000 1.15
+++ frontends/gtk/lyx_gui.C 18 Jul 2004 03:37:49 -0000
@@ -49,6 +49,7 @@
#include <iomanip>
#include <fcntl.h>
#include <boost/bind.hpp>
+#include <boost/function.hpp>
//just for xforms
#include "lyx_forms.h"
@@ -442,19 +443,12 @@ void lyx_gui::remove_read_callback(int f
}
-void lyx_gui::set_datasocket_callback(LyXDataSocket * /* p */)
+void lyx_gui::register_socket_callback(int /*fd*/,
+ boost::function<void()> /*func*/)
{}
-void lyx_gui::remove_datasocket_callback(LyXDataSocket * /* p */)
-{}
-
-
-void lyx_gui::set_serversocket_callback(LyXServerSocket * /* p */)
-{}
-
-
-void lyx_gui::remove_serversocket_callback(LyXServerSocket * /* p */)
+void lyx_gui::unregister_socket_callback(int /*fd*/)
{}
--
Lgb