node_bindings_win.cc 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // Copyright (c) 2013 GitHub, Inc.
  2. // Use of this source code is governed by the MIT license that can be
  3. // found in the LICENSE file.
  4. #include "shell/common/node_bindings_win.h"
  5. #include <windows.h>
  6. #include "base/logging.h"
  7. #include "base/system/sys_info.h"
  8. namespace electron {
  9. NodeBindingsWin::NodeBindingsWin(BrowserEnvironment browser_env)
  10. : NodeBindings(browser_env) {
  11. // on single-core the io comp port NumberOfConcurrentThreads needs to be 2
  12. // to avoid cpu pegging likely caused by a busy loop in PollEvents
  13. if (base::SysInfo::NumberOfProcessors() == 1) {
  14. // the expectation is the uv_loop_ has just been initialized
  15. // which makes iocp replacement safe
  16. CHECK_EQ(0u, uv_loop_->active_handles);
  17. CHECK_EQ(0u, uv_loop_->active_reqs.count);
  18. if (uv_loop_->iocp && uv_loop_->iocp != INVALID_HANDLE_VALUE)
  19. CloseHandle(uv_loop_->iocp);
  20. uv_loop_->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 2);
  21. }
  22. }
  23. NodeBindingsWin::~NodeBindingsWin() = default;
  24. void NodeBindingsWin::PrepareMessageLoop() {
  25. // IOCP does not change for the process until the loop is recreated,
  26. // we ensure that there is only a single polling thread satisfying
  27. // the concurrency limit set from CreateIoCompletionPort call by
  28. // uv_loop_init for the lifetime of this process.
  29. if (initialized_)
  30. return;
  31. NodeBindings::PrepareMessageLoop();
  32. }
  33. void NodeBindingsWin::RunMessageLoop() {
  34. // Avoid calling UvRunOnce if the loop is already active,
  35. // otherwise it can lead to situations were the number of active
  36. // threads processing on IOCP is greater than the concurrency limit.
  37. if (initialized_)
  38. return;
  39. initialized_ = true;
  40. NodeBindings::RunMessageLoop();
  41. }
  42. void NodeBindingsWin::PollEvents() {
  43. // If there are other kinds of events pending, uv_backend_timeout will
  44. // instruct us not to wait.
  45. DWORD bytes, timeout;
  46. ULONG_PTR key;
  47. OVERLAPPED* overlapped;
  48. timeout = uv_backend_timeout(uv_loop_);
  49. GetQueuedCompletionStatus(uv_loop_->iocp, &bytes, &key, &overlapped, timeout);
  50. // Give the event back so libuv can deal with it.
  51. if (overlapped != NULL)
  52. PostQueuedCompletionStatus(uv_loop_->iocp, bytes, key, overlapped);
  53. }
  54. // static
  55. NodeBindings* NodeBindings::Create(BrowserEnvironment browser_env) {
  56. return new NodeBindingsWin(browser_env);
  57. }
  58. } // namespace electron