win_thread.h 3.7 KB

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