OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 10 matching lines...) Expand all Loading... |
21 | 21 |
22 uint32_t UdpSocket2ManagerWindows::_numOfActiveManagers = 0; | 22 uint32_t UdpSocket2ManagerWindows::_numOfActiveManagers = 0; |
23 bool UdpSocket2ManagerWindows::_wsaInit = false; | 23 bool UdpSocket2ManagerWindows::_wsaInit = false; |
24 | 24 |
25 UdpSocket2ManagerWindows::UdpSocket2ManagerWindows() | 25 UdpSocket2ManagerWindows::UdpSocket2ManagerWindows() |
26 : UdpSocketManager(), | 26 : UdpSocketManager(), |
27 _id(-1), | 27 _id(-1), |
28 _stopped(false), | 28 _stopped(false), |
29 _init(false), | 29 _init(false), |
30 _pCrit(CriticalSectionWrapper::CreateCriticalSection()), | 30 _pCrit(CriticalSectionWrapper::CreateCriticalSection()), |
31 _ioCompletionHandle(NULL), | 31 _ioCompletionHandle(nullptr), |
32 _numActiveSockets(0), | 32 _numActiveSockets(0), |
33 _event(EventWrapper::Create()) | 33 _event(EventWrapper::Create()) { |
34 { | 34 _managerNumber = _numOfActiveManagers++; |
35 _managerNumber = _numOfActiveManagers++; | |
36 | 35 |
37 if(_numOfActiveManagers == 1) | 36 if (_numOfActiveManagers == 1) { |
38 { | 37 WORD wVersionRequested = MAKEWORD(2, 2); |
39 WORD wVersionRequested = MAKEWORD(2, 2); | 38 WSADATA wsaData; |
40 WSADATA wsaData; | 39 _wsaInit = WSAStartup(wVersionRequested, &wsaData) == 0; |
41 _wsaInit = WSAStartup(wVersionRequested, &wsaData) == 0; | 40 // TODO (hellner): seems safer to use RAII for this. E.g. what happens |
42 // TODO (hellner): seems safer to use RAII for this. E.g. what happens | 41 // if a UdpSocket2ManagerWindows() created and destroyed |
43 // if a UdpSocket2ManagerWindows() created and destroyed | 42 // without being initialized. |
44 // without being initialized. | 43 } |
45 } | |
46 } | 44 } |
47 | 45 |
48 UdpSocket2ManagerWindows::~UdpSocket2ManagerWindows() | 46 UdpSocket2ManagerWindows::~UdpSocket2ManagerWindows() |
49 { | 47 { |
50 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, | 48 WEBRTC_TRACE(kTraceDebug, kTraceTransport, _id, |
51 "UdpSocket2ManagerWindows(%d)::~UdpSocket2ManagerWindows()", | 49 "UdpSocket2ManagerWindows(%d)::~UdpSocket2ManagerWindows()", |
52 _managerNumber); | 50 _managerNumber); |
53 | 51 |
54 if(_init) | 52 if(_init) |
55 { | 53 { |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 _pCrit->Leave(); | 143 _pCrit->Leave(); |
146 return true; | 144 return true; |
147 } | 145 } |
148 | 146 |
149 bool UdpSocket2ManagerWindows::StartWorkerThreads() | 147 bool UdpSocket2ManagerWindows::StartWorkerThreads() |
150 { | 148 { |
151 if(!_init) | 149 if(!_init) |
152 { | 150 { |
153 _pCrit->Enter(); | 151 _pCrit->Enter(); |
154 | 152 |
155 _ioCompletionHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, | 153 _ioCompletionHandle = |
156 0, 0); | 154 CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0); |
157 if(_ioCompletionHandle == NULL) | 155 if (_ioCompletionHandle == nullptr) { |
158 { | 156 int32_t error = GetLastError(); |
159 int32_t error = GetLastError(); | 157 WEBRTC_TRACE(kTraceError, kTraceTransport, _id, |
160 WEBRTC_TRACE( | 158 "UdpSocket2ManagerWindows(%d)::StartWorkerThreads()" |
161 kTraceError, | 159 "_ioCompletioHandle == null: error:%d", |
162 kTraceTransport, | 160 _managerNumber, error); |
163 _id, | 161 _pCrit->Leave(); |
164 "UdpSocket2ManagerWindows(%d)::StartWorkerThreads()" | 162 return false; |
165 "_ioCompletioHandle == NULL: error:%d", | |
166 _managerNumber,error); | |
167 _pCrit->Leave(); | |
168 return false; | |
169 } | 163 } |
170 | 164 |
171 // Create worker threads. | 165 // Create worker threads. |
172 uint32_t i = 0; | 166 uint32_t i = 0; |
173 bool error = false; | 167 bool error = false; |
174 while(i < _numOfWorkThreads && !error) | 168 while(i < _numOfWorkThreads && !error) |
175 { | 169 { |
176 UdpSocket2WorkerWindows* pWorker = | 170 UdpSocket2WorkerWindows* pWorker = |
177 new UdpSocket2WorkerWindows(_ioCompletionHandle); | 171 new UdpSocket2WorkerWindows(_ioCompletionHandle); |
178 if(pWorker->Init() != 0) | 172 if(pWorker->Init() != 0) |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 threadsStoped, numActicve Sockets=%d", | 261 threadsStoped, numActicve Sockets=%d", |
268 _managerNumber, | 262 _managerNumber, |
269 _numActiveSockets); | 263 _numActiveSockets); |
270 | 264 |
271 // Release all threads waiting for GetQueuedCompletionStatus(..). | 265 // Release all threads waiting for GetQueuedCompletionStatus(..). |
272 if(_ioCompletionHandle) | 266 if(_ioCompletionHandle) |
273 { | 267 { |
274 uint32_t i = 0; | 268 uint32_t i = 0; |
275 for(i = 0; i < _workerThreadsList.size(); i++) | 269 for(i = 0; i < _workerThreadsList.size(); i++) |
276 { | 270 { |
277 PostQueuedCompletionStatus(_ioCompletionHandle, 0 ,0 , NULL); | 271 PostQueuedCompletionStatus(_ioCompletionHandle, 0, 0, nullptr); |
278 } | 272 } |
279 } | 273 } |
280 for (WorkerList::iterator iter = _workerThreadsList.begin(); | 274 for (WorkerList::iterator iter = _workerThreadsList.begin(); |
281 iter != _workerThreadsList.end(); ++iter) { | 275 iter != _workerThreadsList.end(); ++iter) { |
282 if((*iter)->Stop() == false) | 276 if((*iter)->Stop() == false) |
283 { | 277 { |
284 error = -1; | 278 error = -1; |
285 WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, | 279 WEBRTC_TRACE(kTraceWarning, kTraceTransport, -1, |
286 "failed to stop worker thread"); | 280 "failed to stop worker thread"); |
287 } | 281 } |
(...skipping 22 matching lines...) Expand all Loading... |
310 WEBRTC_TRACE( | 304 WEBRTC_TRACE( |
311 kTraceError, | 305 kTraceError, |
312 kTraceTransport, | 306 kTraceTransport, |
313 _id, | 307 _id, |
314 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() manager not\ | 308 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() manager not\ |
315 initialized", | 309 initialized", |
316 _managerNumber); | 310 _managerNumber); |
317 return false; | 311 return false; |
318 } | 312 } |
319 _pCrit->Enter(); | 313 _pCrit->Enter(); |
320 if(s == NULL) | 314 if (s == nullptr) { |
321 { | 315 WEBRTC_TRACE( |
322 WEBRTC_TRACE( | 316 kTraceError, kTraceTransport, _id, |
323 kTraceError, | 317 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket == null", |
324 kTraceTransport, | 318 _managerNumber); |
325 _id, | 319 _pCrit->Leave(); |
326 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket == NULL", | 320 return false; |
327 _managerNumber); | |
328 _pCrit->Leave(); | |
329 return false; | |
330 } | 321 } |
331 if(s->GetFd() == NULL || s->GetFd() == INVALID_SOCKET) | 322 if (s->GetFd() == nullptr || s->GetFd() == INVALID_SOCKET) { |
332 { | 323 WEBRTC_TRACE( |
333 WEBRTC_TRACE( | 324 kTraceError, kTraceTransport, _id, |
334 kTraceError, | 325 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket->GetFd() ==\ |
335 kTraceTransport, | |
336 _id, | |
337 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() socket->GetFd() ==\ | |
338 %d", | 326 %d", |
339 _managerNumber, | 327 _managerNumber, (int32_t)s->GetFd()); |
340 (int32_t)s->GetFd()); | 328 _pCrit->Leave(); |
341 _pCrit->Leave(); | 329 return false; |
342 return false; | |
343 | |
344 } | 330 } |
345 _ioCompletionHandle = CreateIoCompletionPort((HANDLE)s->GetFd(), | 331 _ioCompletionHandle = CreateIoCompletionPort((HANDLE)s->GetFd(), |
346 _ioCompletionHandle, | 332 _ioCompletionHandle, |
347 (ULONG_PTR)(s), 0); | 333 (ULONG_PTR)(s), 0); |
348 if(_ioCompletionHandle == NULL) | 334 if (_ioCompletionHandle == nullptr) { |
349 { | 335 int32_t error = GetLastError(); |
350 int32_t error = GetLastError(); | 336 WEBRTC_TRACE( |
351 WEBRTC_TRACE( | 337 kTraceError, kTraceTransport, _id, |
352 kTraceError, | 338 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() Error adding to IO\ |
353 kTraceTransport, | |
354 _id, | |
355 "UdpSocket2ManagerWindows(%d)::AddSocketPrv() Error adding to IO\ | |
356 completion: %d", | 339 completion: %d", |
357 _managerNumber, | 340 _managerNumber, error); |
358 error); | 341 _pCrit->Leave(); |
359 _pCrit->Leave(); | 342 return false; |
360 return false; | |
361 } | 343 } |
362 _numActiveSockets++; | 344 _numActiveSockets++; |
363 _pCrit->Leave(); | 345 _pCrit->Leave(); |
364 return true; | 346 return true; |
365 } | 347 } |
366 bool UdpSocket2ManagerWindows::RemoveSocketPrv(UdpSocket2Windows* s) | 348 bool UdpSocket2ManagerWindows::RemoveSocketPrv(UdpSocket2Windows* s) |
367 { | 349 { |
368 if(!_init) | 350 if(!_init) |
369 { | 351 { |
370 return false; | 352 return false; |
371 } | 353 } |
372 _pCrit->Enter(); | 354 _pCrit->Enter(); |
373 _numActiveSockets--; | 355 _numActiveSockets--; |
374 if(_numActiveSockets == 0) | 356 if(_numActiveSockets == 0) |
375 { | 357 { |
376 _event->Set(); | 358 _event->Set(); |
377 } | 359 } |
378 _pCrit->Leave(); | 360 _pCrit->Leave(); |
379 return true; | 361 return true; |
380 } | 362 } |
381 | 363 |
382 PerIoContext* UdpSocket2ManagerWindows::PopIoContext() | 364 PerIoContext* UdpSocket2ManagerWindows::PopIoContext() |
383 { | 365 { |
384 if(!_init) | 366 if(!_init) |
385 { | 367 { |
386 return NULL; | 368 return nullptr; |
387 } | 369 } |
388 | 370 |
389 PerIoContext* pIoC = NULL; | 371 PerIoContext* pIoC = nullptr; |
390 if(!_stopped) | 372 if(!_stopped) |
391 { | 373 { |
392 pIoC = _ioContextPool.PopIoContext(); | 374 pIoC = _ioContextPool.PopIoContext(); |
393 }else | 375 }else |
394 { | 376 { |
395 WEBRTC_TRACE( | 377 WEBRTC_TRACE( |
396 kTraceError, | 378 kTraceError, |
397 kTraceTransport, | 379 kTraceTransport, |
398 _id, | 380 _id, |
399 "UdpSocket2ManagerWindows(%d)::PopIoContext() Manager Not started", | 381 "UdpSocket2ManagerWindows(%d)::PopIoContext() Manager Not started", |
400 _managerNumber); | 382 _managerNumber); |
401 } | 383 } |
402 return pIoC; | 384 return pIoC; |
403 } | 385 } |
404 | 386 |
405 int32_t UdpSocket2ManagerWindows::PushIoContext(PerIoContext* pIoContext) | 387 int32_t UdpSocket2ManagerWindows::PushIoContext(PerIoContext* pIoContext) |
406 { | 388 { |
407 return _ioContextPool.PushIoContext(pIoContext); | 389 return _ioContextPool.PushIoContext(pIoContext); |
408 } | 390 } |
409 | 391 |
410 IoContextPool::IoContextPool() | 392 IoContextPool::IoContextPool() |
411 : _pListHead(NULL), | 393 : _pListHead(nullptr), _init(false), _size(0), _inUse(0) {} |
412 _init(false), | |
413 _size(0), | |
414 _inUse(0) | |
415 { | |
416 } | |
417 | 394 |
418 IoContextPool::~IoContextPool() | 395 IoContextPool::~IoContextPool() |
419 { | 396 { |
420 Free(); | 397 Free(); |
421 assert(_size.Value() == 0); | 398 assert(_size.Value() == 0); |
422 AlignedFree(_pListHead); | 399 AlignedFree(_pListHead); |
423 } | 400 } |
424 | 401 |
425 int32_t IoContextPool::Init(uint32_t /*increaseSize*/) | 402 int32_t IoContextPool::Init(uint32_t /*increaseSize*/) |
426 { | 403 { |
427 if(_init) | 404 if(_init) |
428 { | 405 { |
429 return 0; | 406 return 0; |
430 } | 407 } |
431 | 408 |
432 _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), | 409 _pListHead = (PSLIST_HEADER)AlignedMalloc(sizeof(SLIST_HEADER), |
433 MEMORY_ALLOCATION_ALIGNMENT); | 410 MEMORY_ALLOCATION_ALIGNMENT); |
434 if(_pListHead == NULL) | 411 if (_pListHead == nullptr) { |
435 { | 412 return -1; |
436 return -1; | |
437 } | 413 } |
438 InitializeSListHead(_pListHead); | 414 InitializeSListHead(_pListHead); |
439 _init = true; | 415 _init = true; |
440 return 0; | 416 return 0; |
441 } | 417 } |
442 | 418 |
443 PerIoContext* IoContextPool::PopIoContext() | 419 PerIoContext* IoContextPool::PopIoContext() |
444 { | 420 { |
445 if(!_init) | 421 if(!_init) |
446 { | 422 { |
447 return NULL; | 423 return nullptr; |
448 } | 424 } |
449 | 425 |
450 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | 426 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); |
451 if(pListEntry == NULL) | 427 if (pListEntry == nullptr) { |
452 { | 428 IoContextPoolItem* item = (IoContextPoolItem*)AlignedMalloc( |
453 IoContextPoolItem* item = (IoContextPoolItem*) | 429 sizeof(IoContextPoolItem), MEMORY_ALLOCATION_ALIGNMENT); |
454 AlignedMalloc( | 430 if (item == nullptr) { |
455 sizeof(IoContextPoolItem), | 431 return nullptr; |
456 MEMORY_ALLOCATION_ALIGNMENT); | 432 } |
457 if(item == NULL) | 433 memset(&item->payload.ioContext, 0, sizeof(PerIoContext)); |
458 { | 434 item->payload.base = item; |
459 return NULL; | 435 pListEntry = &(item->itemEntry); |
460 } | 436 ++_size; |
461 memset(&item->payload.ioContext,0,sizeof(PerIoContext)); | |
462 item->payload.base = item; | |
463 pListEntry = &(item->itemEntry); | |
464 ++_size; | |
465 } | 437 } |
466 ++_inUse; | 438 ++_inUse; |
467 return &((IoContextPoolItem*)pListEntry)->payload.ioContext; | 439 return &((IoContextPoolItem*)pListEntry)->payload.ioContext; |
468 } | 440 } |
469 | 441 |
470 int32_t IoContextPool::PushIoContext(PerIoContext* pIoContext) | 442 int32_t IoContextPool::PushIoContext(PerIoContext* pIoContext) |
471 { | 443 { |
472 // TODO (hellner): Overlapped IO should be completed at this point. Perhaps | 444 // TODO (hellner): Overlapped IO should be completed at this point. Perhaps |
473 // add an assert? | 445 // add an assert? |
474 const bool overlappedIOCompleted = HasOverlappedIoCompleted( | 446 const bool overlappedIOCompleted = HasOverlappedIoCompleted( |
(...skipping 23 matching lines...) Expand all Loading... |
498 | 470 |
499 int32_t IoContextPool::Free() | 471 int32_t IoContextPool::Free() |
500 { | 472 { |
501 if(!_init) | 473 if(!_init) |
502 { | 474 { |
503 return 0; | 475 return 0; |
504 } | 476 } |
505 | 477 |
506 int32_t itemsFreed = 0; | 478 int32_t itemsFreed = 0; |
507 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); | 479 PSLIST_ENTRY pListEntry = InterlockedPopEntrySList(_pListHead); |
508 while(pListEntry != NULL) | 480 while (pListEntry != nullptr) { |
509 { | 481 IoContextPoolItem* item = ((IoContextPoolItem*)pListEntry); |
510 IoContextPoolItem* item = ((IoContextPoolItem*)pListEntry); | 482 AlignedFree(item); |
511 AlignedFree(item); | 483 --_size; |
512 --_size; | 484 itemsFreed++; |
513 itemsFreed++; | 485 pListEntry = InterlockedPopEntrySList(_pListHead); |
514 pListEntry = InterlockedPopEntrySList(_pListHead); | |
515 } | 486 } |
516 return itemsFreed; | 487 return itemsFreed; |
517 } | 488 } |
518 | 489 |
519 int32_t UdpSocket2WorkerWindows::_numOfWorkers = 0; | 490 int32_t UdpSocket2WorkerWindows::_numOfWorkers = 0; |
520 | 491 |
521 UdpSocket2WorkerWindows::UdpSocket2WorkerWindows(HANDLE ioCompletionHandle) | 492 UdpSocket2WorkerWindows::UdpSocket2WorkerWindows(HANDLE ioCompletionHandle) |
522 : _ioCompletionHandle(ioCompletionHandle), | 493 : _ioCompletionHandle(ioCompletionHandle), |
523 _pThread(Run, this, "UdpSocket2ManagerWindows_thread"), | 494 _pThread(Run, this, "UdpSocket2ManagerWindows_thread"), |
524 _init(false) { | 495 _init(false) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
563 static_cast<UdpSocket2WorkerWindows*>(obj); | 534 static_cast<UdpSocket2WorkerWindows*>(obj); |
564 return pWorker->Process(); | 535 return pWorker->Process(); |
565 } | 536 } |
566 | 537 |
567 // Process should always return true. Stopping the worker threads is done in | 538 // Process should always return true. Stopping the worker threads is done in |
568 // the UdpSocket2ManagerWindows::StopWorkerThreads() function. | 539 // the UdpSocket2ManagerWindows::StopWorkerThreads() function. |
569 bool UdpSocket2WorkerWindows::Process() | 540 bool UdpSocket2WorkerWindows::Process() |
570 { | 541 { |
571 int32_t success = 0; | 542 int32_t success = 0; |
572 DWORD ioSize = 0; | 543 DWORD ioSize = 0; |
573 UdpSocket2Windows* pSocket = NULL; | 544 UdpSocket2Windows* pSocket = nullptr; |
574 PerIoContext* pIOContext = 0; | 545 PerIoContext* pIOContext = 0; |
575 OVERLAPPED* pOverlapped = 0; | 546 OVERLAPPED* pOverlapped = 0; |
576 success = GetQueuedCompletionStatus(_ioCompletionHandle, | 547 success = GetQueuedCompletionStatus(_ioCompletionHandle, |
577 &ioSize, | 548 &ioSize, |
578 (ULONG_PTR*)&pSocket, &pOverlapped, 200); | 549 (ULONG_PTR*)&pSocket, &pOverlapped, 200); |
579 | 550 |
580 uint32_t error = 0; | 551 uint32_t error = 0; |
581 if(!success) | 552 if(!success) |
582 { | 553 { |
583 error = GetLastError(); | 554 error = GetLastError(); |
584 if(error == WAIT_TIMEOUT) | 555 if(error == WAIT_TIMEOUT) |
585 { | 556 { |
586 return true; | 557 return true; |
587 } | 558 } |
588 // This may happen if e.g. PostQueuedCompletionStatus() has been called. | 559 // This may happen if e.g. PostQueuedCompletionStatus() has been called. |
589 // The IO context still needs to be reclaimed or re-used which is done | 560 // The IO context still needs to be reclaimed or re-used which is done |
590 // in UdpSocket2Windows::IOCompleted(..). | 561 // in UdpSocket2Windows::IOCompleted(..). |
591 } | 562 } |
592 if(pSocket == NULL) | 563 if (pSocket == nullptr) { |
593 { | 564 WEBRTC_TRACE( |
594 WEBRTC_TRACE( | 565 kTraceDebug, kTraceTransport, -1, |
595 kTraceDebug, | 566 "UdpSocket2WorkerWindows(%d)::Process(), pSocket == 0, end thread", |
596 kTraceTransport, | 567 _workerNumber); |
597 -1, | 568 return true; |
598 "UdpSocket2WorkerWindows(%d)::Process(), pSocket == 0, end thread", | |
599 _workerNumber); | |
600 return true; | |
601 } | 569 } |
602 pIOContext = (PerIoContext*)pOverlapped; | 570 pIOContext = (PerIoContext*)pOverlapped; |
603 pSocket->IOCompleted(pIOContext,ioSize,error); | 571 pSocket->IOCompleted(pIOContext,ioSize,error); |
604 return true; | 572 return true; |
605 } | 573 } |
606 | 574 |
607 } // namespace test | 575 } // namespace test |
608 } // namespace webrtc | 576 } // namespace webrtc |
OLD | NEW |