| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- // Copyright (c) 2011-present, Facebook, Inc. All rights reserved.
- // This source code is licensed under both the GPLv2 (found in the
- // COPYING file in the root directory) and Apache 2.0 License
- // (found in the LICENSE.Apache file in the root directory).
- //
- // Copyright (c) 2011 The LevelDB Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file. See the AUTHORS file for names of contributors.
- #pragma once
- #include <memory>
- #include <functional>
- #include <type_traits>
- #include "rocksdb/rocksdb_namespace.h"
- namespace ROCKSDB_NAMESPACE {
- namespace port {
- // This class is a replacement for std::thread
- // 2 reasons we do not like std::thread:
- // -- is that it dynamically allocates its internals that are automatically
- // freed when the thread terminates and not on the destruction of the
- // object. This makes it difficult to control the source of memory
- // allocation
- // - This implements Pimpl so we can easily replace the guts of the
- // object in our private version if necessary.
- class WindowsThread {
- struct Data;
- std::shared_ptr<Data> data_;
- unsigned int th_id_;
- void Init(std::function<void()>&&);
- public:
- typedef void* native_handle_type;
- // Construct with no thread
- WindowsThread();
- // Template constructor
- //
- // This templated constructor accomplishes several things
- //
- // - Allows the class as whole to be not a template
- //
- // - take "universal" references to support both _lvalues and _rvalues
- //
- // - because this constructor is a catchall case in many respects it
- // may prevent us from using both the default __ctor, the move __ctor.
- // Also it may circumvent copy __ctor deletion. To work around this
- // we make sure this one has at least one argument and eliminate
- // it from the overload selection when WindowsThread is the first
- // argument.
- //
- // - construct with Fx(Ax...) with a variable number of types/arguments.
- //
- // - Gathers together the callable object with its arguments and constructs
- // a single callable entity
- //
- // - Makes use of std::function to convert it to a specification-template
- // dependent type that both checks the signature conformance to ensure
- // that all of the necessary arguments are provided and allows pimpl
- // implementation.
- template<class Fn,
- class... Args,
- class = typename std::enable_if<
- !std::is_same<typename std::decay<Fn>::type,
- WindowsThread>::value>::type>
- explicit WindowsThread(Fn&& fx, Args&&... ax) :
- WindowsThread() {
- // Use binder to create a single callable entity
- auto binder = std::bind(std::forward<Fn>(fx),
- std::forward<Args>(ax)...);
- // Use std::function to take advantage of the type erasure
- // so we can still hide implementation within pimpl
- // This also makes sure that the binder signature is compliant
- std::function<void()> target = binder;
- Init(std::move(target));
- }
- ~WindowsThread();
- WindowsThread(const WindowsThread&) = delete;
- WindowsThread& operator=(const WindowsThread&) = delete;
- WindowsThread(WindowsThread&&) noexcept;
- WindowsThread& operator=(WindowsThread&&) noexcept;
- bool joinable() const;
- unsigned int get_id() const { return th_id_; }
- native_handle_type native_handle() const;
- static unsigned hardware_concurrency();
- void join();
- bool detach();
- void swap(WindowsThread&);
- };
- } // namespace port
- } // namespace ROCKSDB_NAMESPACE
- namespace std {
- inline void swap(ROCKSDB_NAMESPACE::port::WindowsThread& th1,
- ROCKSDB_NAMESPACE::port::WindowsThread& th2) {
- th1.swap(th2);
- }
- } // namespace std
|