[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Wesnoth-cvs-commits] wesnoth ./changelog src/game.cpp src/multiplaye...
From: |
David White |
Subject: |
[Wesnoth-cvs-commits] wesnoth ./changelog src/game.cpp src/multiplaye... |
Date: |
Thu, 02 Jun 2005 19:10:55 -0400 |
CVSROOT: /cvsroot/wesnoth
Module name: wesnoth
Branch:
Changes by: David White <address@hidden> 05/06/02 23:10:55
Modified files:
. : changelog
src : game.cpp multiplayer.cpp network.cpp
network.hpp show_dialog.cpp show_dialog.hpp
thread.cpp thread.hpp
Log message:
made connecting to a server show a dialog that allows the user to
cancel, rather than blocking
CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/changelog.diff?tr1=1.704&tr2=1.705&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/game.cpp.diff?tr1=1.246&tr2=1.247&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/multiplayer.cpp.diff?tr1=1.158&tr2=1.159&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/network.cpp.diff?tr1=1.61&tr2=1.62&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/network.hpp.diff?tr1=1.24&tr2=1.25&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/show_dialog.cpp.diff?tr1=1.130&tr2=1.131&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/show_dialog.hpp.diff?tr1=1.49&tr2=1.50&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/thread.cpp.diff?tr1=1.4&tr2=1.5&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/wesnoth/wesnoth/src/thread.hpp.diff?tr1=1.2&tr2=1.3&r1=text&r2=text
Patches:
Index: wesnoth/changelog
diff -u wesnoth/changelog:1.704 wesnoth/changelog:1.705
--- wesnoth/changelog:1.704 Thu Jun 2 21:10:47 2005
+++ wesnoth/changelog Thu Jun 2 23:10:55 2005
@@ -1,5 +1,6 @@
CVS HEAD:
* user interface improvements:
+ * made connecting to a server show a dialog that allows the user to cancel
it rather than blocking
* added hotkey for cycle to previous unit (shift-N) (part of #10703)
* added hotkey for hold position (shift-space) (patch 3994)
* made the right Command key on Mac OS X work like the left one
Index: wesnoth/src/game.cpp
diff -u wesnoth/src/game.cpp:1.246 wesnoth/src/game.cpp:1.247
--- wesnoth/src/game.cpp:1.246 Mon May 16 22:44:19 2005
+++ wesnoth/src/game.cpp Thu Jun 2 23:10:55 2005
@@ -1,4 +1,4 @@
-/* $Id: game.cpp,v 1.246 2005/05/16 22:44:19 ydirson Exp $ */
+/* $Id: game.cpp,v 1.247 2005/06/02 23:10:55 Sirp Exp $ */
/*
Copyright (C) 2003 by David White <address@hidden>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -46,7 +46,8 @@
#include "show_dialog.hpp"
#include "sound.hpp"
#include "statistics.hpp"
-#include "team.hpp"
+#include "team.hpp"
+#include "thread.hpp"
#include "titlescreen.hpp"
#include "util.hpp"
#include "unit_types.hpp"
@@ -123,7 +124,8 @@
const char* const * const argv_;
CVideo video_;
-
+
+ const threading::manager thread_manager;
const font::manager font_manager_;
const sound::manager sound_manager_;
const preferences::manager prefs_manager_;
@@ -1008,7 +1010,7 @@
request_terms.add_child("request_terms");
network::send_data(request_terms,sock);
config data;
- sock = network::receive_data(data,sock,60000);
+ sock = network::receive_data(data,sock,5000);
if(!sock) {
gui::show_error_message(disp(), _("Connection timed out"));
return;
@@ -1048,7 +1050,7 @@
std::cerr << "uploading campaign...\n";
network::send_data(data,sock);
- sock = network::receive_data(data,sock,60000);
+ sock = network::receive_data(data,sock,5000);
if(!sock) {
gui::show_error_message(disp(), _("Connection timed out"));
} else if(data.child("error")) {
@@ -1073,7 +1075,7 @@
network::send_data(data,sock);
- sock = network::receive_data(data,sock,60000);
+ sock = network::receive_data(data,sock,5000);
if(!sock) {
gui::show_error_message(disp(), _("Connection timed out"));
} else if(data.child("error")) {
Index: wesnoth/src/multiplayer.cpp
diff -u wesnoth/src/multiplayer.cpp:1.158 wesnoth/src/multiplayer.cpp:1.159
--- wesnoth/src/multiplayer.cpp:1.158 Wed Apr 27 21:11:44 2005
+++ wesnoth/src/multiplayer.cpp Thu Jun 2 23:10:55 2005
@@ -1,4 +1,4 @@
-/* $Id: multiplayer.cpp,v 1.158 2005/04/27 21:11:44 gruikya Exp $ */
+/* $Id: multiplayer.cpp,v 1.159 2005/06/02 23:10:55 Sirp Exp $ */
/*
Copyright (C)
Part of the Battle for Wesnoth Project http://www.wesnoth.org
@@ -120,7 +120,7 @@
config::child_list redirects;
config data;
- sock = network::connect(host, port);
+ sock = gui::network_connect_dialog(disp,_("Connecting to
Server..."),host,port);
do {
@@ -156,8 +156,8 @@
shown_hosts.insert(hostpair(host, port));
if(network::nconnections() > 0)
- network::disconnect();
- sock = network::connect(host, port);
+ network::disconnect();
+ sock = gui::network_connect_dialog(disp,_("Connecting
to Server..."),host,port);
continue;
}
Index: wesnoth/src/network.cpp
diff -u wesnoth/src/network.cpp:1.61 wesnoth/src/network.cpp:1.62
--- wesnoth/src/network.cpp:1.61 Mon May 2 23:48:57 2005
+++ wesnoth/src/network.cpp Thu Jun 2 23:10:55 2005
@@ -4,7 +4,8 @@
#include "config.hpp"
#include "log.hpp"
#include "network.hpp"
-#include "network_worker.hpp"
+#include "network_worker.hpp"
+#include "thread.hpp"
#include "util.hpp"
#include "wassert.hpp"
@@ -230,55 +231,117 @@
{
return server_socket != 0;
}
+
+namespace {
+
+class connect_operation : public threading::async_operation
+{
+public:
+ connect_operation(const std::string& host, int port) : host_(host),
port_(port), error_(NULL), connect_(0)
+ {}
+
+ void check_error();
+ void run();
+
+ network::connection result() const { return connect_; }
+
+private:
+ std::string host_;
+ int port_;
+ const char* error_;
+ network::connection connect_;
+};
+
+void connect_operation::check_error()
+{
+ if(error_ != NULL) {
+ throw error(error_);
+ }
+}
+
+void connect_operation::run()
+{
+ char* const hostname = host_.empty() ? NULL :
const_cast<char*>(host_.c_str());
+ IPaddress ip;
+ if(SDLNet_ResolveHost(&ip,hostname,port_) == -1) {
+ error_ = "Could not connect to host";
+ return;
+ }
+
+ TCPsocket sock = SDLNet_TCP_Open(&ip);
+ if(!sock) {
+ error_ = hostname == NULL ? "Could not bind to port" :
+ "Could not connect to host";
+ return;
+ }
+
+ //if this is a server socket
+ if(hostname == NULL) {
+ const threading::lock l(get_mutex());
+ connect_ = create_connection(sock,"",port_);
+ return;
+ }
+
+ //send data telling the remote host that this is a new connection
+ char buf[4];
+ SDLNet_Write32(0,buf);
+ const int nbytes = SDLNet_TCP_Send(sock,buf,4);
+ if(nbytes != 4) {
+ SDLNet_TCP_Close(sock);
+
+ error_ = "Could not send initial handshake";
+ return;
+ }
+
+ //no blocking operations from here on
+ const threading::lock l(get_mutex());
+ LOG_NW << "sent handshake...\n";
+
+ if(is_aborted()) {
+ LOG_NW << "connect operation aborted by calling thread\n";
+ SDLNet_TCP_Close(sock);
+ return;
+ }
+
+ //allocate this connection a connection handle
+ connect_ = create_connection(sock,host_,port_);
+
+ const int res = SDLNet_TCP_AddSocket(socket_set,sock);
+ if(res == -1) {
+ SDLNet_TCP_Close(sock);
+ error_ = "Could not add socket to socket set";
+ return;
+ }
+
+ waiting_sockets.insert(connect_);
+
+ sockets.push_back(connect_);
+ wassert(schemas.count(connect_) == 0);
+
schemas.insert(std::pair<network::connection,schema_pair>(connect_,schema_pair()));
+
+ notify_finished();
+}
+
+}
connection connect(const std::string& host, int port)
-{
- char* const hostname = host.empty() ?
NULL:const_cast<char*>(host.c_str());
- IPaddress ip;
- if(SDLNet_ResolveHost(&ip,hostname,port) == -1) {
- throw error("Could not connect to host");
- }
-
- TCPsocket sock = SDLNet_TCP_Open(&ip);
- if(!sock) {
- throw error(hostname == NULL ? "Could not bind to port" :
- "Could not connect to host");
- } else {
- //TODO: add code in here which sets the socket to non-blocking
- }
-
- //if this is a server socket
- if(hostname == NULL) {
- return create_connection(sock,"",port);
- }
-
- LOG_NW << "sending handshake...\n";
- //send data telling the remote host that this is a new connection
- char buf[4];
- SDLNet_Write32(0,buf);
- const int nbytes = SDLNet_TCP_Send(sock,buf,4);
- if(nbytes != 4) {
- SDLNet_TCP_Close(sock);
- throw network::error("Could not send initial handshake");
- }
- LOG_NW << "sent handshake...\n";
-
- //allocate this connection a connection handle
- const network::connection connect = create_connection(sock,host,port);
-
- const int res = SDLNet_TCP_AddSocket(socket_set,sock);
- if(res == -1) {
- SDLNet_TCP_Close(sock);
- throw network::error("Could not add socket to socket set");
- }
-
- waiting_sockets.insert(connect);
-
- sockets.push_back(connect);
- wassert(schemas.count(connect) == 0);
-
schemas.insert(std::pair<network::connection,schema_pair>(connect,schema_pair()));
-
- return connect;
+{
+ connect_operation op(host,port);
+ op.run();
+ op.check_error();
+ return op.result();
+}
+
+connection connect(const std::string& host, int port, threading::waiter&
waiter)
+{
+ connect_operation op(host,port);
+ const connect_operation::RESULT res = op.execute(waiter);
+ if(res == connect_operation::ABORTED) {
+ return 0;
+ }
+
+ op.check_error();
+ return op.result();
}
connection accept_connection()
Index: wesnoth/src/network.hpp
diff -u wesnoth/src/network.hpp:1.24 wesnoth/src/network.hpp:1.25
--- wesnoth/src/network.hpp:1.24 Thu Mar 10 20:06:20 2005
+++ wesnoth/src/network.hpp Thu Jun 2 23:10:55 2005
@@ -5,7 +5,12 @@
#include "SDL_net.h"
-#include <string>
+#include <string>
+
+namespace threading
+{
+ class waiter;
+}
//this module wraps the network interface.
@@ -57,7 +62,9 @@
//function to attempt to connect to a remote host. Returns
//the new connection on success, or 0 on failure.
//throws error.
-connection connect(const std::string& host, int port=15000);
+connection connect(const std::string& host, int port=15000);
+
+connection connect(const std::string& host, int port, threading::waiter&
waiter);
//function to accept a connection from a remote host. If no
//host is attempting to connect, it will return 0 immediately.
Index: wesnoth/src/show_dialog.cpp
diff -u wesnoth/src/show_dialog.cpp:1.130 wesnoth/src/show_dialog.cpp:1.131
--- wesnoth/src/show_dialog.cpp:1.130 Tue May 17 22:19:40 2005
+++ wesnoth/src/show_dialog.cpp Thu Jun 2 23:10:55 2005
@@ -1,4 +1,4 @@
-/* $Id: show_dialog.cpp,v 1.130 2005/05/17 22:19:40 ydirson Exp $ */
+/* $Id: show_dialog.cpp,v 1.131 2005/06/02 23:10:55 Sirp Exp $ */
/*
Copyright (C) 2003 by David White <address@hidden>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -27,7 +27,8 @@
#include "key.hpp"
#include "log.hpp"
#include "playlevel.hpp"
-#include "show_dialog.hpp"
+#include "show_dialog.hpp"
+#include "thread.hpp"
#include "language.hpp"
#include "sdl_utils.hpp"
#include "tooltips.hpp"
@@ -888,6 +889,55 @@
return res;
}
}
+}
+
+namespace {
+
+class connect_waiter : public threading::waiter
+{
+public:
+ connect_waiter(display& disp, gui::button& button) : disp_(disp),
button_(button)
+ {}
+ ACTION process();
+
+private:
+ display& disp_;
+ gui::button& button_;
+};
+
+connect_waiter::ACTION connect_waiter::process()
+{
+ events::raise_draw_event();
+ disp_.flip();
+ events::pump();
+ if(button_.pressed()) {
+ return ABORT;
+ } else {
+ return WAIT;
+ }
+}
+
+}
+
+network::connection network_connect_dialog(display& disp, const std::string&
msg, const std::string& hostname, int port)
+{
+ const size_t width = 250;
+ const size_t height = 20;
+ const size_t border = 20;
+ const int left = disp.x()/2 - width/2;
+ const int top = disp.y()/2 - height/2;
+
+ gui::button cancel_button(disp.video(),_("Cancel"));
+ std::vector<gui::button*> buttons_ptr(1,&cancel_button);
+
+ surface_restorer restorer;
+
gui::draw_dialog(left,top,width,height,disp.video(),msg,NULL,&buttons_ptr,&restorer);
+
+ events::raise_draw_event();
+ disp.flip();
+
+ connect_waiter waiter(disp,cancel_button);
+ return network::connect(hostname,port,waiter);
}
} //end namespace gui
Index: wesnoth/src/show_dialog.hpp
diff -u wesnoth/src/show_dialog.hpp:1.49 wesnoth/src/show_dialog.hpp:1.50
--- wesnoth/src/show_dialog.hpp:1.49 Mon May 16 22:44:20 2005
+++ wesnoth/src/show_dialog.hpp Thu Jun 2 23:10:55 2005
@@ -1,4 +1,4 @@
-/* $Id: show_dialog.hpp,v 1.49 2005/05/16 22:44:20 ydirson Exp $ */
+/* $Id: show_dialog.hpp,v 1.50 2005/06/02 23:10:55 Sirp Exp $ */
/*
Copyright (C) 2003 by David White <address@hidden>
Part of the Battle for Wesnoth Project http://wesnoth.whitevine.net
@@ -141,6 +141,7 @@
void show_error_message(display &disp, std::string const &message);
network::connection network_data_dialog(display& disp, const std::string& msg,
config& cfg, network::connection connection_num=0);
+network::connection network_connect_dialog(display& disp, const std::string&
msg, const std::string& hostname, int port);
void check_quit(CVideo &video);
Index: wesnoth/src/thread.cpp
diff -u wesnoth/src/thread.cpp:1.4 wesnoth/src/thread.cpp:1.5
--- wesnoth/src/thread.cpp:1.4 Sun Dec 5 19:09:47 2004
+++ wesnoth/src/thread.cpp Thu Jun 2 23:10:55 2005
@@ -1,8 +1,33 @@
#include "global.hpp"
-#include "thread.hpp"
+#include "thread.hpp"
+
+#include <iostream>
+#include <vector>
+
+namespace {
+
+int run_async_operation(void* data)
+{
+ threading::async_operation* const op =
reinterpret_cast<threading::async_operation*>(data);
+ op->run();
+ op->notify_finished(); //in case the operation didn't notify of
finishing
+
+ return 0;
+}
+
+std::vector<SDL_Thread*> detached_threads;
+
+}
namespace threading {
+
+manager::~manager()
+{
+ for(std::vector<SDL_Thread*>::iterator i = detached_threads.begin(); i
!= detached_threads.end(); ++i) {
+ SDL_WaitThread(*i,NULL);
+ }
+}
thread::thread(int (*f)(void*), void* data) : thread_(SDL_CreateThread(f,data))
{}
@@ -26,6 +51,12 @@
SDL_WaitThread(thread_,NULL);
thread_ = NULL;
}
+}
+
+void thread::detach()
+{
+ detached_threads.push_back(thread_);
+ thread_ = NULL;
}
mutex::mutex() : m_(SDL_CreateMutex())
@@ -59,12 +90,16 @@
return SDL_CondWait(cond_,m.m_) == 0;
}
-#if 0
-bool condition::wait_timeout(const mutex& m, unsigned int timeout)
+condition::WAIT_TIMEOUT_RESULT condition::wait_timeout(const mutex& m,
unsigned int timeout)
{
- return SDL_CondWaitTimeout(cond_,m.m_,timeout) == 0;
+ const int res = SDL_CondWaitTimeout(cond_,m.m_,timeout) == 0;
+ switch(res) {
+ //the SDL documentation appears backward on when these results are
returned
+ case 0: return WAIT_TIMEOUT;
+ case SDL_MUTEX_TIMEDOUT: return WAIT_OK;
+ default: return WAIT_ERROR;
+ }
}
-#endif
void condition::notify_one()
{
@@ -75,5 +110,31 @@
{
SDL_CondBroadcast(cond_);
}
+
+void async_operation::notify_finished()
+{
+ finished_.notify_one();
+}
+
+async_operation::RESULT async_operation::execute(waiter& wait)
+{
+ const lock l(get_mutex());
+ thread t(run_async_operation,this);
+
+ while(wait.process() == waiter::WAIT) {
+ std::cerr << "process...\n";
+ const condition::WAIT_TIMEOUT_RESULT res =
finished_.wait_timeout(get_mutex(),20);
+ if(res == condition::WAIT_OK) {
+ return COMPLETED;
+ } else if(res == condition::WAIT_ERROR) {
+ break;
+ }
+ }
+
+ aborted_ = true;
+ t.detach();
+ return ABORTED;
+}
+
}
Index: wesnoth/src/thread.hpp
diff -u wesnoth/src/thread.hpp:1.2 wesnoth/src/thread.hpp:1.3
--- wesnoth/src/thread.hpp:1.2 Sun Dec 5 19:09:47 2004
+++ wesnoth/src/thread.hpp Thu Jun 2 23:10:55 2005
@@ -9,7 +9,12 @@
// This module defines primitives for wrapping C++ around SDL's threading
// interface
namespace threading
-{
+{
+
+struct manager
+{
+ ~manager();
+};
// Threading object.
//
@@ -42,7 +47,9 @@
// Join (wait) on the thread to finish. When the thread finishes,
// the function will return. calling wait() on an already killed
// thread is a no-op.
- void join();
+ void join();
+
+ void detach();
private:
thread(const thread&);
void operator=(const thread&);
@@ -125,20 +132,19 @@
//
// \pre You have already aquired a lock on mutex m
//
- bool wait(const mutex& m);
+ bool wait(const mutex& m);
+
+ enum WAIT_TIMEOUT_RESULT { WAIT_OK, WAIT_TIMEOUT, WAIT_ERROR };
+
// wait on the condition with a timeout. Basically the same as the
// wait() function, but if the lock is not aquired before the
// timeout, the function returns with an error.
//
// \param m the mutex you wish free the lock for.
// \param timeout the allowed timeout in milliseconds (ms)
- // \returns true: success, false: an error occurred
- //
- // \todo This function cannot check for timeout, which is to
- // check on the SDL constant SDL_MUTEX_TIMEDOUT. Thus this
- // function cannot check if the error was due to something malformed
- // or if the time ran out.
- bool wait_timeout(const mutex& m, unsigned int timeout);
+ // \returns result based on whether condition was met, it timed out,
+ // or there was an error
+ WAIT_TIMEOUT_RESULT wait_timeout(const mutex& m, unsigned int timeout);
// signal the condition and wake up one thread waiting on the
// condition. If no thread is waiting, notify_one() is a no-op.
// Does not unlock the mutex.
@@ -160,6 +166,46 @@
void operator=(const condition&);
SDL_cond* const cond_;
+};
+
+class waiter {
+public:
+ enum ACTION { WAIT, ABORT };
+
+ virtual ~waiter() {}
+ virtual ACTION process() = 0;
+};
+
+class async_operation
+{
+public:
+
+ enum RESULT { COMPLETED, ABORTED };
+
+ async_operation() : aborted_(false) {}
+ virtual ~async_operation() {}
+
+ RESULT execute(waiter& wait);
+
+ mutex& get_mutex() { return mutex_; }
+
+ virtual void run() = 0;
+
+ //notify that the operation is finished. Can be called from within the
thread
+ //while holding the mutex and after checking is_aborted()
+ //if we want to be sure that if the operation is completed, the caller
is notified.
+ //will be called in any case after the operation returns
+ void notify_finished();
+
+protected:
+
+ //must hold the mutex before calling this function
+ bool is_aborted() const { return aborted_; }
+
+private:
+ bool aborted_;
+ condition finished_;
+ mutex mutex_;
};
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Wesnoth-cvs-commits] wesnoth ./changelog src/game.cpp src/multiplaye...,
David White <=