TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
NetworkThread.h
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef NetworkThread_h__
19 #define NetworkThread_h__
20 
21 #include "Define.h"
22 #include "Errors.h"
23 #include "Log.h"
24 #include "Timer.h"
25 #include <boost/asio/ip/tcp.hpp>
26 #include <boost/asio/deadline_timer.hpp>
27 #include <atomic>
28 #include <chrono>
29 #include <memory>
30 #include <mutex>
31 #include <set>
32 #include <thread>
33 
34 using boost::asio::ip::tcp;
35 
36 template<class SocketType>
38 {
39 public:
42  {
43  }
44 
45  virtual ~NetworkThread()
46  {
47  Stop();
48  if (_thread)
49  {
50  Wait();
51  delete _thread;
52  }
53  }
54 
55  void Stop()
56  {
57  _stopped = true;
58  _io_service.stop();
59  }
60 
61  bool Start()
62  {
63  if (_thread)
64  return false;
65 
66  _thread = new std::thread(&NetworkThread::Run, this);
67  return true;
68  }
69 
70  void Wait()
71  {
72  ASSERT(_thread);
73 
74  _thread->join();
75  delete _thread;
76  _thread = nullptr;
77  }
78 
80  {
81  return _connections;
82  }
83 
84  virtual void AddSocket(std::shared_ptr<SocketType> sock)
85  {
86  std::lock_guard<std::mutex> lock(_newSocketsLock);
87 
88  ++_connections;
89  _newSockets.push_back(sock);
90  SocketAdded(sock);
91  }
92 
93  tcp::socket* GetSocketForAccept() { return &_acceptSocket; }
94 
95 protected:
96  virtual void SocketAdded(std::shared_ptr<SocketType> /*sock*/) { }
97  virtual void SocketRemoved(std::shared_ptr<SocketType> /*sock*/) { }
98 
100  {
101  std::lock_guard<std::mutex> lock(_newSocketsLock);
102 
103  if (_newSockets.empty())
104  return;
105 
106  for (std::shared_ptr<SocketType> sock : _newSockets)
107  {
108  if (!sock->IsOpen())
109  {
110  SocketRemoved(sock);
111  --_connections;
112  }
113  else
114  _sockets.push_back(sock);
115  }
116 
117  _newSockets.clear();
118  }
119 
120  void Run()
121  {
122  TC_LOG_DEBUG("misc", "Network Thread Starting");
123 
124  _updateTimer.expires_from_now(boost::posix_time::milliseconds(10));
125  _updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
126  _io_service.run();
127 
128  TC_LOG_DEBUG("misc", "Network Thread exits");
129  _newSockets.clear();
130  _sockets.clear();
131  }
132 
133  void Update()
134  {
135  if (_stopped)
136  return;
137 
138  _updateTimer.expires_from_now(boost::posix_time::milliseconds(10));
139  _updateTimer.async_wait(std::bind(&NetworkThread<SocketType>::Update, this));
140 
141  AddNewSockets();
142 
143  _sockets.erase(std::remove_if(_sockets.begin(), _sockets.end(), [this](std::shared_ptr<SocketType> sock)
144  {
145  if (!sock->Update())
146  {
147  if (sock->IsOpen())
148  sock->CloseSocket();
149 
150  this->SocketRemoved(sock);
151 
152  --this->_connections;
153  return true;
154  }
155 
156  return false;
157  }), _sockets.end());
158  }
159 
160 private:
161  typedef std::vector<std::shared_ptr<SocketType>> SocketContainer;
162 
163  std::atomic<int32> _connections;
164  std::atomic<bool> _stopped;
165 
166  std::thread* _thread;
167 
168  SocketContainer _sockets;
169 
170  std::mutex _newSocketsLock;
171  SocketContainer _newSockets;
172 
173  boost::asio::io_service _io_service;
174  tcp::socket _acceptSocket;
175  boost::asio::deadline_timer _updateTimer;
176 };
177 
178 #endif // NetworkThread_h__
boost::asio::io_service _io_service
Definition: NetworkThread.h:173
virtual void AddSocket(std::shared_ptr< SocketType > sock)
Definition: NetworkThread.h:84
int32 GetConnectionCount() const
Definition: NetworkThread.h:79
SocketContainer _newSockets
Definition: NetworkThread.h:171
void Run()
Definition: NetworkThread.h:120
#define false
Definition: CascPort.h:18
std::atomic< bool > _stopped
Definition: NetworkThread.h:164
#define TC_LOG_DEBUG(filterType__,...)
Definition: Log.h:198
void Update()
Definition: NetworkThread.h:133
NetworkThread()
Definition: NetworkThread.h:40
SocketContainer _sockets
Definition: NetworkThread.h:168
void Wait()
Definition: NetworkThread.h:70
std::atomic< int32 > _connections
Definition: NetworkThread.h:163
virtual ~NetworkThread()
Definition: NetworkThread.h:45
void Stop()
Definition: NetworkThread.h:55
Definition: NetworkThread.h:37
std::vector< std::shared_ptr< SocketType > > SocketContainer
Definition: NetworkThread.h:161
std::thread * _thread
Definition: NetworkThread.h:166
tcp::socket _acceptSocket
Definition: NetworkThread.h:174
std::mutex _newSocketsLock
Definition: NetworkThread.h:170
int32_t int32
Definition: Define.h:146
virtual void SocketRemoved(std::shared_ptr< SocketType >)
Definition: NetworkThread.h:97
boost::asio::deadline_timer _updateTimer
Definition: NetworkThread.h:175
float milliseconds()
Definition: units.h:92
void AddNewSockets()
Definition: NetworkThread.h:99
#define ASSERT
Definition: Errors.h:55
bool Start()
Definition: NetworkThread.h:61
virtual void SocketAdded(std::shared_ptr< SocketType >)
Definition: NetworkThread.h:96
tcp::socket * GetSocketForAccept()
Definition: NetworkThread.h:93