/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "rtc_base/platform_thread.h"

#include <algorithm>
#include <optional>
#include <string>
#include <utility>

#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "rtc_base/platform_thread_types.h"

#if !defined(WEBRTC_WIN)
#include <sched.h>
#endif

#include "rtc_base/checks.h"

namespace webrtc {
namespace {

#if defined(WEBRTC_WIN)
int Win32PriorityFromThreadPriority(ThreadPriority priority) {
  switch (priority) {
    case ThreadPriority::kLow:
      return THREAD_PRIORITY_BELOW_NORMAL;
    case ThreadPriority::kNormal:
      return THREAD_PRIORITY_NORMAL;
    case ThreadPriority::kHigh:
      return THREAD_PRIORITY_ABOVE_NORMAL;
    case ThreadPriority::kRealtime:
      return THREAD_PRIORITY_TIME_CRITICAL;
  }
}
#endif

bool SetPriority(ThreadPriority priority) {
#if defined(WEBRTC_WIN)
  return SetThreadPriority(GetCurrentThread(),
                           Win32PriorityFromThreadPriority(priority)) != FALSE;
#elif defined(WEBRTC_FUCHSIA) || \
    (defined(__EMSCRIPTEN__) && !defined(__EMSCRIPTEN_PTHREADS__))
  // Setting thread priorities is not supported in NaCl, Fuchsia or Emscripten
  // without pthreads.
  return true;
#elif defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
  // TODO(tommi): Switch to the same mechanism as Chromium uses for changing
  // thread priorities.
  return true;
#else
  const int policy = SCHED_FIFO;
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  // Convert webrtc priority to system priorities:
  sched_param param;
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;
  switch (priority) {
    case ThreadPriority::kLow:
      param.sched_priority = low_prio;
      break;
    case ThreadPriority::kNormal:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      param.sched_priority = (low_prio + top_prio - 1) / 2;
      break;
    case ThreadPriority::kHigh:
      param.sched_priority = std::max(top_prio - 2, low_prio);
      break;
    case ThreadPriority::kRealtime:
      param.sched_priority = top_prio;
      break;
  }
  return pthread_setschedparam(pthread_self(), policy, &param) == 0;
#endif  // defined(WEBRTC_WIN)
}

#if defined(WEBRTC_WIN)
DWORD WINAPI RunPlatformThread(void* param) {
  // The GetLastError() function only returns valid results when it is called
  // after a Win32 API function that returns a "failed" result. A crash dump
  // contains the result from GetLastError() and to make sure it does not
  // falsely report a Windows error we call SetLastError here.
  ::SetLastError(ERROR_SUCCESS);
  auto function = static_cast<absl::AnyInvocable<void() &&>*>(param);
  std::move (*function)();
  delete function;
  return 0;
}
#else
void* RunPlatformThread(void* param) {
  auto function = static_cast<absl::AnyInvocable<void() &&>*>(param);
  std::move (*function)();
  delete function;
  return nullptr;
}
#endif  // defined(WEBRTC_WIN)

}  // namespace

PlatformThread::PlatformThread(Handle handle, bool joinable)
    : handle_(handle), joinable_(joinable) {}

PlatformThread::PlatformThread(PlatformThread&& rhs)
    : handle_(rhs.handle_), joinable_(rhs.joinable_) {
  rhs.handle_ = std::nullopt;
}

PlatformThread& PlatformThread::operator=(PlatformThread&& rhs) {
  Finalize();
  handle_ = rhs.handle_;
  joinable_ = rhs.joinable_;
  rhs.handle_ = std::nullopt;
  return *this;
}

PlatformThread::~PlatformThread() {
  Finalize();
}

PlatformThread PlatformThread::SpawnJoinable(
    absl::AnyInvocable<void() &&> thread_function,
    absl::string_view name,
    ThreadAttributes attributes) {
  return SpawnThread(std::move(thread_function), name, attributes,
                     /*joinable=*/true);
}

PlatformThread PlatformThread::SpawnDetached(
    absl::AnyInvocable<void() &&> thread_function,
    absl::string_view name,
    ThreadAttributes attributes) {
  return SpawnThread(std::move(thread_function), name, attributes,
                     /*joinable=*/false);
}

std::optional<PlatformThread::Handle> PlatformThread::GetHandle() const {
  return handle_;
}

#if defined(WEBRTC_WIN)
bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) {
  RTC_DCHECK(handle_.has_value());
  return handle_.has_value() ? QueueUserAPC(function, *handle_, data) != FALSE
                             : false;
}
#endif

void PlatformThread::Finalize() {
  if (!handle_.has_value())
    return;
#if defined(WEBRTC_WIN)
  if (joinable_)
    WaitForSingleObject(*handle_, INFINITE);
  CloseHandle(*handle_);
#else
  if (joinable_)
    RTC_CHECK_EQ(0, pthread_join(*handle_, nullptr));
#endif
  handle_ = std::nullopt;
}

PlatformThread PlatformThread::SpawnThread(
    absl::AnyInvocable<void() &&> thread_function,
    absl::string_view name,
    ThreadAttributes attributes,
    bool joinable) {
  RTC_DCHECK(thread_function);
  RTC_DCHECK(!name.empty());
  // TODO(tommi): Consider lowering the limit to 15 (limit on Linux).
  RTC_DCHECK(name.length() < 64);
  auto start_thread_function_ptr = new absl::AnyInvocable<void() &&>(
      [thread_function = std::move(thread_function), name = std::string(name),
       attributes]() mutable {
        SetCurrentThreadName(name.c_str());
        SetPriority(attributes.priority);
        std::move(thread_function)();
      });
#if defined(WEBRTC_WIN)
  // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
  // Set the reserved stack stack size to 1M, which is the default on Windows
  // and Linux.
  DWORD thread_id = 0;
  PlatformThread::Handle handle = ::CreateThread(
      nullptr, 1024 * 1024, &RunPlatformThread, start_thread_function_ptr,
      STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id);
  RTC_CHECK(handle) << "CreateThread failed";
#else
  pthread_attr_t attr;
  pthread_attr_init(&attr);
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  pthread_attr_setdetachstate(
      &attr, joinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
  PlatformThread::Handle handle;
  RTC_CHECK_EQ(0, pthread_create(&handle, &attr, &RunPlatformThread,
                                 start_thread_function_ptr));
  pthread_attr_destroy(&attr);
#endif  // defined(WEBRTC_WIN)
  return PlatformThread(handle, joinable);
}

}  // namespace webrtc
