text: // Copyright (c) 2018 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.
  
  // Prevent Windows headers from defining min/max macros and instead
  // use STL.
  #ifndef NOMINMAX
  #define NOMINMAX
  #endif  // ifndef NOMINMAX
  #include <windows.h>
  
  #include <algorithm>
  #include <atomic>
  #include <chrono>
  #include <condition_variable>
  #include <cstddef>
  #include <cstdint>
  #include <cstdlib>
  #include <cstring>
  #include <memory>
  #include <mutex>
  #include <queue>
  #include <sstream>
  #include <string>
  #include <vector>
  
  #include "leveldb/env.h"
  #include "leveldb/slice.h"
  #include "port/port.h"
  #include "port/thread_annotations.h"
  #include "util/env_windows_test_helper.h"
  #include "util/logging.h"
  #include "util/mutexlock.h"
  #include "util/windows_logger.h"
  
  namespace leveldb {
  
  namespace {
  
  constexpr const size_t kWritableFileBufferSize = 65536;
  
  // Up to 1000 mmaps for 64-bit binaries; none for 32-bit.
  constexpr int kDefaultMmapLimit = (sizeof(void*) >= 8) ? 1000 : 0;
  
  // Can be set by by EnvWindowsTestHelper::SetReadOnlyMMapLimit().
  int g_mmap_limit = kDefaultMmapLimit;
  
  std::string GetWindowsErrorMessage(DWORD error_code) {
    std::string message;
    char* error_text = nullptr;
    // Use MBCS version of FormatMessage to match return value.
    size_t error_text_size = ::FormatMessageA(
        FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER |
            FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        reinterpret_cast<char*>(&error_text), 0, nullptr);
    if (!error_text) {
      return message;
    }
    message.assign(error_text, error_text_size);
    ::LocalFree(error_text);
    return message;
  }
  
  Status WindowsError(const std::string& context, DWORD error_code) {
    if (error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_PATH_NOT_FOUND)
      return Status::NotFound(context, GetWindowsErrorMessage(error_code));
    return Status::IOError(context, GetWindowsErrorMessage(error_code));
  }
  
  class ScopedHandle {
   public:
    ScopedHandle(HANDLE handle) : handle_(handle) {}
    ScopedHandle(const ScopedHandle&) = delete;
    ScopedHandle(ScopedHandle&& other) noexcept : handle_(other.Release()) {}
    ~ScopedHandle() { Close(); }
  
    ScopedHandle& operator=(const ScopedHandle&) = delete;
  
    ScopedHandle& operator=(ScopedHandle&& rhs) noexcept {
      if (this != &rhs) handle_ = rhs.Release();
      return *this;
    }
  
    bool Close() {
      if (!is_valid()) {
        return true;
      }
      HANDLE h = handle_;
      handle_ = INVALID_HANDLE_VALUE;
      return ::CloseHandle(h);
    }
  
    bool is_valid() const {
      return handle_ != INVALID_HANDLE_VALUE && handle_ != nullptr;
    }
  
    HANDLE get() const { return handle_; }
  
    HANDLE Release() {
      HANDLE h = handle_;
      handle_ = INVALID_HANDLE_VALUE;
      return h;
    }
  
   private:
    HANDLE handle_;
  };
  
  // Helper class to limit resource usage to avoid exhaustion.
  // Currently used to limit read-only file descriptors and mmap file usage
  // so that we do not run out of file descriptors or virtual memory, or run into
  // kernel performance problems for very large databases.
  class Limiter {
   public:
    // Limit maximum number of resources to |max_acquires|.
    Limiter(int max_acquires) : acquires_allowed_(max_acquires) {}
  
    Limiter(const Limiter&) = delete;
    Limiter operator=(const Limiter&) = delete;
  
    // If another resource is available, acquire it and return true.
    // Else return false.
    bool Acquire() {
      int old_acquires_allowed =
          acquires_allowed_.fetch_sub(1, std::memory_order_relaxed);
  
      if (old_acquires_allowed > 0) return true;
  
      acquires_allowed_.fetch_add(1, std::memory_order_relaxed);
      return false;
    }
  
    // Release a resource acquired by a previous call to Acquire() that returned
    // true.
    void Release() { acquires_allowed_.fetch_add(1, std::memory_order_relaxed); }
  
   private:
    // The number of available resources.
    //
    // This is a counter and is not tied to the invariants of any other class, so
    // it can be operated on safely using std::memory_order_relaxed.
    std::atomic<int> acquires_allowed_;
  };
  
  class WindowsSequentialFile : public SequentialFile {
   public:
    WindowsSequentialFile(std::string filename, ScopedHandle handle)
        : handle_(std::move(handle)), filename_(std::move(filename)) {}
    ~WindowsSequentialFile() override {}
  
    Status Read(size_t n, Slice* result, char* scratch) override {
      DWORD bytes_read;
      // DWORD is 32-bit, but size_t could technically be larger. However leveldb
      // files are limited to leveldb::Options::max_file_size which is clamped to
      // 1<<30 or 1 GiB.
      assert(n <= std::numeric_limits<DWORD>::max());
      if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
                      nullptr)) {
        return WindowsError(filename_, ::GetLastError());
      }
  
      *result = Slice(scratch, bytes_read);
      return Status::OK();
    }
  
    Status Skip(uint64_t n) override {
      LARGE_INTEGER distance;
      distance.QuadPart = n;
      if (!::SetFilePointerEx(handle_.get(), distance, nullptr, FILE_CURRENT)) {
        return WindowsError(filename_, ::GetLastError());
      }
      return Status::OK();
    }
  
   private:
    const ScopedHandle handle_;
    const std::string filename_;
  };
  
  class WindowsRandomAccessFile : public RandomAccessFile {
   public:
    WindowsRandomAccessFile(std::string filename, ScopedHandle handle)
        : handle_(std::move(handle)), filename_(std::move(filename)) {}
  
    ~WindowsRandomAccessFile() override = default;
  
    Status Read(uint64_t offset, size_t n, Slice* result,
                char* scratch) const override {
      DWORD bytes_read = 0;
      OVERLAPPED overlapped = {0};
  
      overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
      overlapped.Offset = static_cast<DWORD>(offset);
      if (!::ReadFile(handle_.get(), scratch, static_cast<DWORD>(n), &bytes_read,
                      &overlapped)) {
        DWORD error_code = ::GetLastError();
        if (error_code != ERROR_HANDLE_EOF) {
          *result = Slice(scratch, 0);
          return Status::IOError(filename_, GetWindowsErrorMessage(error_code));
        }
      }
  
      *result = Slice(scratch, bytes_read);
      return Status::OK();
    }
  
   private:
    const ScopedHandle handle_;
    const std::string filename_;
  };
  
  class WindowsMmapReadableFile : public RandomAccessFile {
   public:
    // base[0,length-1] contains the mmapped contents of the file.
    WindowsMmapReadableFile(std::string filename, char* mmap_base, size_t length,
                            Limiter* mmap_limiter)
        : mmap_base_(mmap_base),
          length_(length),
          mmap_limiter_(mmap_limiter),
          filename_(std::move(filename)) {}
  
    ~WindowsMmapReadableFile() override {
      ::UnmapViewOfFile(mmap_base_);
      mmap_limiter_->Release();
    }
  
    Status Read(uint64_t offset, size_t n, Slice* result,
                char* scratch) const override {
      if (offset + n > length_) {
        *result = Slice();
        return WindowsError(filename_, ERROR_INVALID_PARAMETER);
      }
  
      *result = Slice(mmap_base_ + offset, n);
      return Status::OK();
    }
  
   private:
    char* const mmap_base_;
    const size_t length_;
    Limiter* const mmap_limiter_;
    const std::string filename_;
  };
  
  class WindowsWritableFile : public WritableFile {
   public:
    WindowsWritableFile(std::string filename, ScopedHandle handle)
        : pos_(0), handle_(std::move(handle)), filename_(std::move(filename)) {}
  
    ~WindowsWritableFile() override = default;
  
    Status Append(const Slice& data) override {
      size_t write_size = data.size();
      const char* write_data = data.data();
  
      // Fit as much as possible into buffer.
      size_t copy_size = std::min(write_size, kWritableFileBufferSize - pos_);
      std::memcpy(buf_ + pos_, write_data, copy_size);
      write_data += copy_size;
      write_size -= copy_size;
      pos_ += copy_size;
      if (write_size == 0) {
        return Status::OK();
      }
  
      // Can't fit in buffer, so need to do at least one write.
      Status status = FlushBuffer();
      if (!status.ok()) {
        return status;
      }
  
      // Small writes go to buffer, large writes are written directly.
      if (write_size < kWritableFileBufferSize) {
        std::memcpy(buf_, write_data, write_size);
        pos_ = write_size;
        return Status::OK();
      }
      return WriteUnbuffered(write_data, write_size);
    }
  
    Status Close() override {
      Status status = FlushBuffer();
      if (!handle_.Close() && status.ok()) {
        status = WindowsError(filename_, ::GetLastError());
      }
      return status;
    }
  
    Status Flush() override { return FlushBuffer(); }
  
    Status Sync() override {
      // On Windows no need to sync parent directory. Its metadata will be updated
      // via the creation of the new file, without an explicit sync.
  
      Status status = FlushBuffer();
      if (!status.ok()) {
        return status;
      }
  
      if (!::FlushFileBuffers(handle_.get())) {
        return Status::IOError(filename_,
                               GetWindowsErrorMessage(::GetLastError()));
      }
      return Status::OK();
    }
  
   private:
    Status FlushBuffer() {
      Status status = WriteUnbuffered(buf_, pos_);
      pos_ = 0;
      return status;
    }
  
    Status WriteUnbuffered(const char* data, size_t size) {
      DWORD bytes_written;
      if (!::WriteFile(handle_.get(), data, static_cast<DWORD>(size),
                       &bytes_written, nullptr)) {
        return Status::IOError(filename_,
                               GetWindowsErrorMessage(::GetLastError()));
      }
      return Status::OK();
    }
  
    // buf_[0, pos_-1] contains data to be written to handle_.
    char buf_[kWritableFileBufferSize];
    size_t pos_;
  
    ScopedHandle handle_;
    const std::string filename_;
  };
  
  // Lock or unlock the entire file as specified by |lock|. Returns true
  // when successful, false upon failure. Caller should call ::GetLastError()
  // to determine cause of failure
  bool LockOrUnlock(HANDLE handle, bool lock) {
    if (lock) {
      return ::LockFile(handle,
                        /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
                        /*nNumberOfBytesToLockLow=*/MAXDWORD,
                        /*nNumberOfBytesToLockHigh=*/MAXDWORD);
    } else {
      return ::UnlockFile(handle,
                          /*dwFileOffsetLow=*/0, /*dwFileOffsetHigh=*/0,
                          /*nNumberOfBytesToLockLow=*/MAXDWORD,
                          /*nNumberOfBytesToLockHigh=*/MAXDWORD);
    }
  }
  
  class WindowsFileLock : public FileLock {
   public:
    WindowsFileLock(ScopedHandle handle, std::string filename)
        : handle_(std::move(handle)), filename_(std::move(filename)) {}
  
    const ScopedHandle& handle() const { return handle_; }
    const std::string& filename() const { return filename_; }
  
   private:
    const ScopedHandle handle_;
    const std::string filename_;
  };
  
  class WindowsEnv : public Env {
   public:
    WindowsEnv();
    ~WindowsEnv() override {
      static const char msg[] =
          "WindowsEnv singleton destroyed. Unsupported behavior!\n";
      std::fwrite(msg, 1, sizeof(msg), stderr);
      std::abort();
    }
  
    Status NewSequentialFile(const std::string& filename,
                             SequentialFile** result) override {
      *result = nullptr;
      DWORD desired_access = GENERIC_READ;
      DWORD share_mode = FILE_SHARE_READ;
      ScopedHandle handle = ::CreateFileA(
          filename.c_str(), desired_access, share_mode,
          /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
          /*hTemplateFile=*/nullptr);
      if (!handle.is_valid()) {
        return WindowsError(filename, ::GetLastError());
      }
  
      *result = new WindowsSequentialFile(filename, std::move(handle));
      return Status::OK();
    }
  
    Status NewRandomAccessFile(const std::string& filename,
                               RandomAccessFile** result) override {
      *result = nullptr;
      DWORD desired_access = GENERIC_READ;
      DWORD share_mode = FILE_SHARE_READ;
      ScopedHandle handle =
          ::CreateFileA(filename.c_str(), desired_access, share_mode,
                        /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
                        FILE_ATTRIBUTE_READONLY,
                        /*hTemplateFile=*/nullptr);
      if (!handle.is_valid()) {
        return WindowsError(filename, ::GetLastError());
      }
      if (!mmap_limiter_.Acquire()) {
        *result = new WindowsRandomAccessFile(filename, std::move(handle));
        return Status::OK();
      }
  
      LARGE_INTEGER file_size;
      Status status;
      if (!::GetFileSizeEx(handle.get(), &file_size)) {
        mmap_limiter_.Release();
        return WindowsError(filename, ::GetLastError());
      }
  
      ScopedHandle mapping =
          ::CreateFileMappingA(handle.get(),
                               /*security attributes=*/nullptr, PAGE_READONLY,
                               /*dwMaximumSizeHigh=*/0,
                               /*dwMaximumSizeLow=*/0,
                               /*lpName=*/nullptr);
      if (mapping.is_valid()) {
        void* mmap_base = ::MapViewOfFile(mapping.get(), FILE_MAP_READ,
                                          /*dwFileOffsetHigh=*/0,
                                          /*dwFileOffsetLow=*/0,
                                          /*dwNumberOfBytesToMap=*/0);
        if (mmap_base) {
          *result = new WindowsMmapReadableFile(
              filename, reinterpret_cast<char*>(mmap_base),
              static_cast<size_t>(file_size.QuadPart), &mmap_limiter_);
          return Status::OK();
        }
      }
      mmap_limiter_.Release();
      return WindowsError(filename, ::GetLastError());
    }
  
    Status NewWritableFile(const std::string& filename,
                           WritableFile** result) override {
      DWORD desired_access = GENERIC_WRITE;
      DWORD share_mode = 0;  // Exclusive access.
      ScopedHandle handle = ::CreateFileA(
          filename.c_str(), desired_access, share_mode,
          /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
          /*hTemplateFile=*/nullptr);
      if (!handle.is_valid()) {
        *result = nullptr;
        return WindowsError(filename, ::GetLastError());
      }
  
      *result = new WindowsWritableFile(filename, std::move(handle));
      return Status::OK();
    }
  
    Status NewAppendableFile(const std::string& filename,
                             WritableFile** result) override {
      DWORD desired_access = FILE_APPEND_DATA;
      DWORD share_mode = 0;  // Exclusive access.
      ScopedHandle handle = ::CreateFileA(
          filename.c_str(), desired_access, share_mode,
          /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
          /*hTemplateFile=*/nullptr);
      if (!handle.is_valid()) {
        *result = nullptr;
        return WindowsError(filename, ::GetLastError());
      }
  
      *result = new WindowsWritableFile(filename, std::move(handle));
      return Status::OK();
    }
  
    bool FileExists(const std::string& filename) override {
      return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
    }
  
    Status GetChildren(const std::string& directory_path,
                       std::vector<std::string>* result) override {
      const std::string find_pattern = directory_path + "\\*";
      WIN32_FIND_DATAA find_data;
      HANDLE dir_handle = ::FindFirstFileA(find_pattern.c_str(), &find_data);
      if (dir_handle == INVALID_HANDLE_VALUE) {
        DWORD last_error = ::GetLastError();
        if (last_error == ERROR_FILE_NOT_FOUND) {
          return Status::OK();
        }
        return WindowsError(directory_path, last_error);
      }
      do {
        char base_name[_MAX_FNAME];
        char ext[_MAX_EXT];
  
        if (!_splitpath_s(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
                          ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
          result->emplace_back(std::string(base_name) + ext);
        }
      } while (::FindNextFileA(dir_handle, &find_data));
      DWORD last_error = ::GetLastError();
      ::FindClose(dir_handle);
      if (last_error != ERROR_NO_MORE_FILES) {
        return WindowsError(directory_path, last_error);
      }
      return Status::OK();
    }
  
    Status RemoveFile(const std::string& filename) override {
      if (!::DeleteFileA(filename.c_str())) {
        return WindowsError(filename, ::GetLastError());
      }
      return Status::OK();
    }
  
    Status CreateDir(const std::string& dirname) override {
      if (!::CreateDirectoryA(dirname.c_str(), nullptr)) {
        return WindowsError(dirname, ::GetLastError());
      }
      return Status::OK();
    }
  
    Status RemoveDir(const std::string& dirname) override {
      if (!::RemoveDirectoryA(dirname.c_str())) {
        return WindowsError(dirname, ::GetLastError());
      }
      return Status::OK();
    }
  
    Status GetFileSize(const std::string& filename, uint64_t* size) override {
      WIN32_FILE_ATTRIBUTE_DATA file_attributes;
      if (!::GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
                                  &file_attributes)) {
        return WindowsError(filename, ::GetLastError());
      }
      ULARGE_INTEGER file_size;
      file_size.HighPart = file_attributes.nFileSizeHigh;
      file_size.LowPart = file_attributes.nFileSizeLow;
      *size = file_size.QuadPart;
      return Status::OK();
    }
  
    Status RenameFile(const std::string& from, const std::string& to) override {
      // Try a simple move first. It will only succeed when |to| doesn't already
      // exist.
      if (::MoveFileA(from.c_str(), to.c_str())) {
        return Status::OK();
      }
      DWORD move_error = ::GetLastError();
  
      // Try the full-blown replace if the move fails, as ReplaceFile will only
      // succeed when |to| does exist. When writing to a network share, we may not
      // be able to change the ACLs. Ignore ACL errors then
      // (REPLACEFILE_IGNORE_MERGE_ERRORS).
      if (::ReplaceFileA(to.c_str(), from.c_str(), /*lpBackupFileName=*/nullptr,
                         REPLACEFILE_IGNORE_MERGE_ERRORS,
                         /*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
        return Status::OK();
      }
      DWORD replace_error = ::GetLastError();
      // In the case of FILE_ERROR_NOT_FOUND from ReplaceFile, it is likely that
      // |to| does not exist. In this case, the more relevant error comes from the
      // call to MoveFile.
      if (replace_error == ERROR_FILE_NOT_FOUND ||
          replace_error == ERROR_PATH_NOT_FOUND) {
        return WindowsError(from, move_error);
      } else {
        return WindowsError(from, replace_error);
      }
    }
  
    Status LockFile(const std::string& filename, FileLock** lock) override {
      *lock = nullptr;
      Status result;
      ScopedHandle handle = ::CreateFileA(
          filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
          /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
          nullptr);
      if (!handle.is_valid()) {
        result = WindowsError(filename, ::GetLastError());
      } else if (!LockOrUnlock(handle.get(), true)) {
        result = WindowsError("lock " + filename, ::GetLastError());
      } else {
        *lock = new WindowsFileLock(std::move(handle), filename);
      }
      return result;
    }
  
    Status UnlockFile(FileLock* lock) override {
      WindowsFileLock* windows_file_lock =
          reinterpret_cast<WindowsFileLock*>(lock);
      if (!LockOrUnlock(windows_file_lock->handle().get(), false)) {
        return WindowsError("unlock " + windows_file_lock->filename(),
                            ::GetLastError());
      }
      delete windows_file_lock;
      return Status::OK();
    }
  
    void Schedule(void (*background_work_function)(void* background_work_arg),
                  void* background_work_arg) override;
  
    void StartThread(void (*thread_main)(void* thread_main_arg),
                     void* thread_main_arg) override {
      std::thread new_thread(thread_main, thread_main_arg);
      new_thread.detach();
    }
  
    Status GetTestDirectory(std::string* result) override {
      const char* env = getenv("TEST_TMPDIR");
      if (env && env[0] != '\0') {
        *result = env;
        return Status::OK();
      }
  
      char tmp_path[MAX_PATH];
      if (!GetTempPathA(ARRAYSIZE(tmp_path), tmp_path)) {
        return WindowsError("GetTempPath", ::GetLastError());
      }
      std::stringstream ss;
      ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();
      *result = ss.str();
  
      // Directory may already exist
      CreateDir(*result);
      return Status::OK();
    }
  
    Status NewLogger(const std::string& filename, Logger** result) override {
      std::FILE* fp = std::fopen(filename.c_str(), "w");
      if (fp == nullptr) {
        *result = nullptr;
        return WindowsError(filename, ::GetLastError());
      } else {
        *result = new WindowsLogger(fp);
        return Status::OK();
      }
    }
  
    uint64_t NowMicros() override {
      // GetSystemTimeAsFileTime typically has a resolution of 10-20 msec.
      // TODO(cmumford): Switch to GetSystemTimePreciseAsFileTime which is
      // available in Windows 8 and later.
      FILETIME ft;
      ::GetSystemTimeAsFileTime(&ft);
      // Each tick represents a 100-nanosecond intervals since January 1, 1601
      // (UTC).
      uint64_t num_ticks =
          (static_cast<uint64_t>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
      return num_ticks / 10;
    }
  
    void SleepForMicroseconds(int micros) override {
      std::this_thread::sleep_for(std::chrono::microseconds(micros));
    }
  
   private:
    void BackgroundThreadMain();
  
    static void BackgroundThreadEntryPoint(WindowsEnv* env) {
      env->BackgroundThreadMain();
    }
  
    // Stores the work item data in a Schedule() call.
    //
    // Instances are constructed on the thread calling Schedule() and used on the
    // background thread.
    //
    // This structure is thread-safe beacuse it is immutable.
    struct BackgroundWorkItem {
      explicit BackgroundWorkItem(void (*function)(void* arg), void* arg)
          : function(function), arg(arg) {}
  
      void (*const function)(void*);
      void* const arg;
    };
  
    port::Mutex background_work_mutex_;
    port::CondVar background_work_cv_ GUARDED_BY(background_work_mutex_);
    bool started_background_thread_ GUARDED_BY(background_work_mutex_);
  
    std::queue<BackgroundWorkItem> background_work_queue_
        GUARDED_BY(background_work_mutex_);
  
    Limiter mmap_limiter_;  // Thread-safe.
  };
  
  // Return the maximum number of concurrent mmaps.
  int MaxMmaps() { return g_mmap_limit; }
  
  WindowsEnv::WindowsEnv()
      : background_work_cv_(&background_work_mutex_),
        started_background_thread_(false),
        mmap_limiter_(MaxMmaps()) {}
  
  void WindowsEnv::Schedule(
      void (*background_work_function)(void* background_work_arg),
      void* background_work_arg) {
    background_work_mutex_.Lock();
  
    // Start the background thread, if we haven't done so already.
    if (!started_background_thread_) {
      started_background_thread_ = true;
      std::thread background_thread(WindowsEnv::BackgroundThreadEntryPoint, this);
      background_thread.detach();
    }
  
    // If the queue is empty, the background thread may be waiting for work.
    if (background_work_queue_.empty()) {
      background_work_cv_.Signal();
    }
  
    background_work_queue_.emplace(background_work_function, background_work_arg);
    background_work_mutex_.Unlock();
  }
  
  void WindowsEnv::BackgroundThreadMain() {
    while (true) {
      background_work_mutex_.Lock();
  
      // Wait until there is work to be done.
      while (background_work_queue_.empty()) {
        background_work_cv_.Wait();
      }
  
      assert(!background_work_queue_.empty());
      auto background_work_function = background_work_queue_.front().function;
      void* background_work_arg = background_work_queue_.front().arg;
      background_work_queue_.pop();
  
      background_work_mutex_.Unlock();
      background_work_function(background_work_arg);
    }
  }
  
  // Wraps an Env instance whose destructor is never created.
  //
  // Intended usage:
  //   using PlatformSingletonEnv = SingletonEnv<PlatformEnv>;
  //   void ConfigurePosixEnv(int param) {
  //     PlatformSingletonEnv::AssertEnvNotInitialized();
  //     // set global configuration flags.
  //   }
  //   Env* Env::Default() {
  //     static PlatformSingletonEnv default_env;
  //     return default_env.env();
  //   }
  template <typename EnvType>
  class SingletonEnv {
   public:
    SingletonEnv() {
  #if !defined(NDEBUG)
      env_initialized_.store(true, std::memory_order::memory_order_relaxed);
  #endif  // !defined(NDEBUG)
      static_assert(sizeof(env_storage_) >= sizeof(EnvType),
                    "env_storage_ will not fit the Env");
      static_assert(alignof(decltype(env_storage_)) >= alignof(EnvType),
                    "env_storage_ does not meet the Env's alignment needs");
      new (&env_storage_) EnvType();
    }
    ~SingletonEnv() = default;
  
    SingletonEnv(const SingletonEnv&) = delete;
    SingletonEnv& operator=(const SingletonEnv&) = delete;
  
    Env* env() { return reinterpret_cast<Env*>(&env_storage_); }
  
    static void AssertEnvNotInitialized() {
  #if !defined(NDEBUG)
      assert(!env_initialized_.load(std::memory_order::memory_order_relaxed));
  #endif  // !defined(NDEBUG)
    }
  
   private:
    typename std::aligned_storage<sizeof(EnvType), alignof(EnvType)>::type
        env_storage_;
  #if !defined(NDEBUG)
    static std::atomic<bool> env_initialized_;
  #endif  // !defined(NDEBUG)
  };
  
  #if !defined(NDEBUG)
  template <typename EnvType>
  std::atomic<bool> SingletonEnv<EnvType>::env_initialized_;
  #endif  // !defined(NDEBUG)
  
  using WindowsDefaultEnv = SingletonEnv<WindowsEnv>;
  
  }  // namespace
  
  void EnvWindowsTestHelper::SetReadOnlyMMapLimit(int limit) {
    WindowsDefaultEnv::AssertEnvNotInitialized();
    g_mmap_limit = limit;
  }
  
  Env* Env::Default() {
    static WindowsDefaultEnv env_container;
    return env_container.env();
  }
  
  }  // namespace leveldb
  