win_thread.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
  2. // This source code is licensed under both the GPLv2 (found in the
  3. // COPYING file in the root directory) and Apache 2.0 License
  4. // (found in the LICENSE.Apache file in the root directory).
  5. //
  6. // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
  7. // Use of this source code is governed by a BSD-style license that can be
  8. // found in the LICENSE file. See the AUTHORS file for names of contributors.
  9. #pragma once
  10. #include <memory>
  11. #include <functional>
  12. #include <type_traits>
  13. #include "rocksdb/rocksdb_namespace.h"
  14. namespace ROCKSDB_NAMESPACE {
  15. namespace port {
  16. // This class is a replacement for std::thread
  17. // 2 reasons we do not like std::thread:
  18. // -- is that it dynamically allocates its internals that are automatically
  19. // freed when the thread terminates and not on the destruction of the
  20. // object. This makes it difficult to control the source of memory
  21. // allocation
  22. // - This implements Pimpl so we can easily replace the guts of the
  23. // object in our private version if necessary.
  24. class WindowsThread {
  25. struct Data;
  26. std::shared_ptr<Data> data_;
  27. unsigned int th_id_;
  28. void Init(std::function<void()>&&);
  29. public:
  30. typedef void* native_handle_type;
  31. // Construct with no thread
  32. WindowsThread();
  33. // Template constructor
  34. //
  35. // This templated constructor accomplishes several things
  36. //
  37. // - Allows the class as whole to be not a template
  38. //
  39. // - take "universal" references to support both _lvalues and _rvalues
  40. //
  41. // - because this constructor is a catchall case in many respects it
  42. // may prevent us from using both the default __ctor, the move __ctor.
  43. // Also it may circumvent copy __ctor deletion. To work around this
  44. // we make sure this one has at least one argument and eliminate
  45. // it from the overload selection when WindowsThread is the first
  46. // argument.
  47. //
  48. // - construct with Fx(Ax...) with a variable number of types/arguments.
  49. //
  50. // - Gathers together the callable object with its arguments and constructs
  51. // a single callable entity
  52. //
  53. // - Makes use of std::function to convert it to a specification-template
  54. // dependent type that both checks the signature conformance to ensure
  55. // that all of the necessary arguments are provided and allows pimpl
  56. // implementation.
  57. template<class Fn,
  58. class... Args,
  59. class = typename std::enable_if<
  60. !std::is_same<typename std::decay<Fn>::type,
  61. WindowsThread>::value>::type>
  62. explicit WindowsThread(Fn&& fx, Args&&... ax) :
  63. WindowsThread() {
  64. // Use binder to create a single callable entity
  65. auto binder = std::bind(std::forward<Fn>(fx),
  66. std::forward<Args>(ax)...);
  67. // Use std::function to take advantage of the type erasure
  68. // so we can still hide implementation within pimpl
  69. // This also makes sure that the binder signature is compliant
  70. std::function<void()> target = binder;
  71. Init(std::move(target));
  72. }
  73. ~WindowsThread();
  74. WindowsThread(const WindowsThread&) = delete;
  75. WindowsThread& operator=(const WindowsThread&) = delete;
  76. WindowsThread(WindowsThread&&) noexcept;
  77. WindowsThread& operator=(WindowsThread&&) noexcept;
  78. bool joinable() const;
  79. unsigned int get_id() const { return th_id_; }
  80. native_handle_type native_handle() const;
  81. static unsigned hardware_concurrency();
  82. void join();
  83. bool detach();
  84. void swap(WindowsThread&);
  85. };
  86. } // namespace port
  87. } // namespace ROCKSDB_NAMESPACE
  88. namespace std {
  89. inline void swap(ROCKSDB_NAMESPACE::port::WindowsThread& th1,
  90. ROCKSDB_NAMESPACE::port::WindowsThread& th2) {
  91. th1.swap(th2);
  92. }
  93. } // namespace std