@@ -67,7 +67,10 @@ static void asyncCallbackTrampoline(uv_async_t* handle) {
67
67
device->asyncCallback ();
68
68
}
69
69
70
- static void asyncCloseCallback (uv_handle_t * handle) {}
70
+ static void asyncCloseCallbackTrampoline (uv_handle_t * handle) {
71
+ PCSX::FTDI::Device* device = reinterpret_cast <PCSX::FTDI::Device*>(handle->data );
72
+ device->asyncCloseCallback ();
73
+ }
71
74
72
75
PCSX::FTDI::Device::Device () {
73
76
uv_async_init (s_gui->loop (), &m_async, asyncCallbackTrampoline);
@@ -79,7 +82,9 @@ PCSX::FTDI::Device::~Device() {
79
82
assert (!m_private->m_event );
80
83
assert (!m_private->m_handle );
81
84
delete m_private;
82
- uv_close (reinterpret_cast <uv_handle_t *>(&m_async), asyncCloseCallback);
85
+ uv_loop_t * loop = m_async.loop ;
86
+ uv_close (reinterpret_cast <uv_handle_t *>(&m_async), asyncCloseCallbackTrampoline);
87
+ while (!m_asyncClosed) uv_run (loop, UV_RUN_ONCE);
83
88
}
84
89
85
90
void PCSX::FTDI::Device::open () {
@@ -216,6 +221,31 @@ void PCSX::FTDI::Devices::stopThread() {
216
221
217
222
bool PCSX::FTDI::Devices::isThreadRunning () { return s_threadRunning; }
218
223
224
+ void PCSX::FTDI::Devices::shutdown () {
225
+ if (!isThreadRunning ()) startThread ();
226
+ {
227
+ bool run = true ;
228
+ while (run) {
229
+ run = false ;
230
+ std::unique_lock<std::shared_mutex> guard (s_listLock);
231
+ for (unsigned i = 0 ; i < s_numDevs; i++) {
232
+ auto & device = s_devices[i];
233
+ switch (device.m_private ->m_state ) {
234
+ case Private::DeviceData::STATE_OPENED:
235
+ device.close ();
236
+ case Private::DeviceData::STATE_CLOSE_PENDING:
237
+ case Private::DeviceData::STATE_OPEN_PENDING:
238
+ run = true ;
239
+ break ;
240
+ }
241
+ }
242
+ }
243
+ }
244
+ stopThread ();
245
+ delete[] s_devices;
246
+ s_numDevs = 0 ;
247
+ }
248
+
219
249
void PCSX::FTDI::Devices::setGUI (GUI* gui) { s_gui = gui; }
220
250
221
251
#endif
0 commit comments