Fix: Data races on cursor state in OpenGL backends
[openttd-github.git] / src / network / core / tcp_connect.cpp
blobb4485cfe96c7d1af2faee70d3e84e29433d768db
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /**
9 * @file tcp_connect.cpp Basic functions to create connections without blocking.
12 #include "../../stdafx.h"
13 #include "../../thread.h"
15 #include "tcp.h"
17 #include "../../safeguards.h"
19 /** List of connections that are currently being created */
20 static std::vector<TCPConnecter *> _tcp_connecters;
22 /**
23 * Create a new connecter for the given address
24 * @param address the (un)resolved address to connect to
26 TCPConnecter::TCPConnecter(const NetworkAddress &address) :
27 connected(false),
28 aborted(false),
29 killed(false),
30 sock(INVALID_SOCKET),
31 address(address)
33 _tcp_connecters.push_back(this);
34 if (!StartNewThread(nullptr, "ottd:tcp", &TCPConnecter::ThreadEntry, this)) {
35 this->Connect();
39 /** The actual connection function */
40 void TCPConnecter::Connect()
42 this->sock = this->address.Connect();
43 if (this->sock == INVALID_SOCKET) {
44 this->aborted = true;
45 } else {
46 this->connected = true;
50 /**
51 * Entry point for the new threads.
52 * @param param the TCPConnecter instance to call Connect on.
54 /* static */ void TCPConnecter::ThreadEntry(TCPConnecter *param)
56 param->Connect();
59 /**
60 * Check whether we need to call the callback, i.e. whether we
61 * have connected or aborted and call the appropriate callback
62 * for that. It's done this way to ease on the locking that
63 * would otherwise be needed everywhere.
65 /* static */ void TCPConnecter::CheckCallbacks()
67 for (auto iter = _tcp_connecters.begin(); iter < _tcp_connecters.end(); /* nothing */) {
68 TCPConnecter *cur = *iter;
69 const bool connected = cur->connected.load();
70 const bool aborted = cur->aborted.load();
71 if ((connected || aborted) && cur->killed) {
72 iter = _tcp_connecters.erase(iter);
73 if (cur->sock != INVALID_SOCKET) closesocket(cur->sock);
74 delete cur;
75 continue;
77 if (connected) {
78 iter = _tcp_connecters.erase(iter);
79 cur->OnConnect(cur->sock);
80 delete cur;
81 continue;
83 if (aborted) {
84 iter = _tcp_connecters.erase(iter);
85 cur->OnFailure();
86 delete cur;
87 continue;
89 iter++;
93 /** Kill all connection attempts. */
94 /* static */ void TCPConnecter::KillAll()
96 for (TCPConnecter *conn : _tcp_connecters) conn->killed = true;