KiCad PCB EDA Suite
ASYNC_SOCKET_HOLDER Class Reference

Spins up a thread to send messages via a socket. More...

Public Member Functions

 ASYNC_SOCKET_HOLDER ()
 
 ~ASYNC_SOCKET_HOLDER ()
 
bool Send (int aService, const std::string &aMessage)
 Attempts to send a message if the thread is available. More...
 

Private Member Functions

void worker ()
 Actual task that sends data to the socket server. More...
 

Private Attributes

std::thread m_thread
 
std::pair< int, std::string > m_message
 
bool m_messageReady
 
std::mutex m_mutex
 
std::condition_variable m_cv
 
bool m_shutdown
 

Detailed Description

Spins up a thread to send messages via a socket.

No message queuing, if a message is in flight when another is posted with Send(), the second is just dropped. This is a workaround for "non-blocking" sockets not always being non-blocking, especially on Windows. It is kept fairly simple and not exposed to the outside world because it should be replaced in a future KiCad version with a real message queue of some sort, and unified with the Kiway messaging system.

Definition at line 132 of file eda_dde.cpp.

Constructor & Destructor Documentation

◆ ASYNC_SOCKET_HOLDER()

ASYNC_SOCKET_HOLDER::ASYNC_SOCKET_HOLDER ( )
inline

Definition at line 135 of file eda_dde.cpp.

135  :
136  m_messageReady( false ),
137  m_shutdown( false )
138  {
139  // Do a dummy Connect so that wx will set up the socket stuff on the main thread, which is
140  // required even if you later make socket connections on another thread.
141  wxSocketClient* client = new wxSocketClient;
142  wxIPV4address addr;
143 
144  addr.Hostname( HOSTNAME );
145  addr.Service( KICAD_PCB_PORT_SERVICE_NUMBER );
146 
147  client->Connect( addr, false );
148 
149  client->Close();
150  client->Destroy();
151 
152  m_thread = std::thread( &ASYNC_SOCKET_HOLDER::worker, this );
153  }
#define KICAD_PCB_PORT_SERVICE_NUMBER
< Pcbnew listens on this port for commands from Eeschema
Definition: eda_dde.h:40
std::thread m_thread
Definition: eda_dde.cpp:294
static const wxString HOSTNAME(wxT("localhost"))
void worker()
Actual task that sends data to the socket server.
Definition: eda_dde.cpp:198

References HOSTNAME(), KICAD_PCB_PORT_SERVICE_NUMBER, m_thread, and worker().

◆ ~ASYNC_SOCKET_HOLDER()

ASYNC_SOCKET_HOLDER::~ASYNC_SOCKET_HOLDER ( )
inline

Definition at line 155 of file eda_dde.cpp.

156  {
157  {
158  std::lock_guard<std::mutex> lock( m_mutex );
159  m_shutdown = true;
160  }
161 
162  m_cv.notify_one();
163 
164  try
165  {
166  if( m_thread.joinable() )
167  m_thread.join();
168  }
169  catch( ... )
170  {
171  }
172  }
std::mutex m_mutex
Definition: eda_dde.cpp:297
std::thread m_thread
Definition: eda_dde.cpp:294
std::condition_variable m_cv
Definition: eda_dde.cpp:298

References m_cv, m_mutex, m_shutdown, and m_thread.

Member Function Documentation

◆ Send()

bool ASYNC_SOCKET_HOLDER::Send ( int  aService,
const std::string &  aMessage 
)
inline

Attempts to send a message if the thread is available.

Parameters
aServiceis the port number (i.e. service) to send to
aMessageis the message to send
Returns
true if the message was queued

Definition at line 180 of file eda_dde.cpp.

181  {
182  if( m_messageReady )
183  return false;
184 
185  std::lock_guard<std::mutex> lock( m_mutex );
186 
187  m_message = std::make_pair( aService, aMessage );
188  m_messageReady = true;
189  m_cv.notify_one();
190 
191  return true;
192  }
std::mutex m_mutex
Definition: eda_dde.cpp:297
std::condition_variable m_cv
Definition: eda_dde.cpp:298
std::pair< int, std::string > m_message
Definition: eda_dde.cpp:295

References m_cv, m_message, m_messageReady, and m_mutex.

◆ worker()

void ASYNC_SOCKET_HOLDER::worker ( )
inlineprivate

Actual task that sends data to the socket server.

Definition at line 198 of file eda_dde.cpp.

199  {
200  int port;
201  std::string message;
202 
203  std::unique_lock<std::mutex> lock( m_mutex );
204 
205  while( !m_shutdown )
206  {
207  m_cv.wait( lock, [&]() { return m_messageReady || m_shutdown; } );
208 
209  if( m_shutdown )
210  break;
211 
212  port = m_message.first;
213  message = m_message.second;
214 
215  lock.unlock();
216 
217  wxSocketClient* sock_client;
218  wxIPV4address addr;
219 
220  // Create a connexion
221  addr.Hostname( HOSTNAME );
222  addr.Service( port );
223 
224  // Mini-tutorial for Connect() :-)
225  // (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample)
226  // ---------------------------
227  //
228  // There are two ways to use Connect(): blocking and non-blocking,
229  // depending on the value passed as the 'wait' (2nd) parameter.
230  //
231  // Connect(addr, true) will wait until the connection completes,
232  // returning true on success and false on failure. This call blocks
233  // the GUI (this might be changed in future releases to honor the
234  // wxSOCKET_BLOCK flag).
235  //
236  // Connect(addr, false) will issue a nonblocking connection request
237  // and return immediately. If the return value is true, then the
238  // connection has been already successfully established. If it is
239  // false, you must wait for the request to complete, either with
240  // WaitOnConnect() or by watching wxSOCKET_CONNECTION / LOST
241  // events (please read the documentation).
242  //
243  // WaitOnConnect() itself never blocks the GUI (this might change
244  // in the future to honor the wxSOCKET_BLOCK flag). This call will
245  // return false on timeout, or true if the connection request
246  // completes, which in turn might mean:
247  //
248  // a) That the connection was successfully established
249  // b) That the connection request failed (for example, because
250  // it was refused by the peer.
251  //
252  // Use IsConnected() to distinguish between these two.
253  //
254  // So, in a brief, you should do one of the following things:
255  //
256  // For blocking Connect:
257  //
258  // bool success = client->Connect(addr, true);
259  //
260  // For nonblocking Connect:
261  //
262  // client->Connect(addr, false);
263  //
264  // bool waitmore = true;
265  // while (! client->WaitOnConnect(seconds, millis) && waitmore )
266  // {
267  // // possibly give some feedback to the user,
268  // // update waitmore if needed.
269  // }
270  // bool success = client->IsConnected();
271  //
272  // And that's all :-)
273 
274  sock_client = new wxSocketClient( wxSOCKET_BLOCK );
275  sock_client->SetTimeout( 1 ); // Time out in Seconds
276  sock_client->Connect( addr, false );
277  sock_client->WaitOnConnect( 0, 250 );
278 
279  if( sock_client->Ok() && sock_client->IsConnected() )
280  {
281  sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ );
282  sock_client->Write( message.c_str(), message.length() );
283  }
284 
285  sock_client->Close();
286  sock_client->Destroy();
287 
288  m_messageReady = false;
289 
290  lock.lock();
291  }
292  }
std::mutex m_mutex
Definition: eda_dde.cpp:297
static const wxString HOSTNAME(wxT("localhost"))
std::condition_variable m_cv
Definition: eda_dde.cpp:298
std::pair< int, std::string > m_message
Definition: eda_dde.cpp:295

References HOSTNAME(), m_cv, m_message, m_messageReady, m_mutex, and m_shutdown.

Referenced by ASYNC_SOCKET_HOLDER().

Member Data Documentation

◆ m_cv

std::condition_variable ASYNC_SOCKET_HOLDER::m_cv
private

Definition at line 298 of file eda_dde.cpp.

Referenced by Send(), worker(), and ~ASYNC_SOCKET_HOLDER().

◆ m_message

std::pair<int, std::string> ASYNC_SOCKET_HOLDER::m_message
private

Definition at line 295 of file eda_dde.cpp.

Referenced by Send(), and worker().

◆ m_messageReady

bool ASYNC_SOCKET_HOLDER::m_messageReady
private

Definition at line 296 of file eda_dde.cpp.

Referenced by Send(), and worker().

◆ m_mutex

std::mutex ASYNC_SOCKET_HOLDER::m_mutex
mutableprivate

Definition at line 297 of file eda_dde.cpp.

Referenced by Send(), worker(), and ~ASYNC_SOCKET_HOLDER().

◆ m_shutdown

bool ASYNC_SOCKET_HOLDER::m_shutdown
private

Definition at line 299 of file eda_dde.cpp.

Referenced by worker(), and ~ASYNC_SOCKET_HOLDER().

◆ m_thread

std::thread ASYNC_SOCKET_HOLDER::m_thread
private

Definition at line 294 of file eda_dde.cpp.

Referenced by ASYNC_SOCKET_HOLDER(), and ~ASYNC_SOCKET_HOLDER().


The documentation for this class was generated from the following file: