/*
 *  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 <memory>

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

#include "rtc_base/checks.h"

namespace rtc {
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(__native_client__) || 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<std::function<void()>*>(param);
  (*function)();
  delete function;
  return 0;
}
#else
void* RunPlatformThread(void* param) {
  auto function = static_cast<std::function<void()>*>(param);
  (*function)();
  delete function;
  return 0;
}
#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(
    std::function<void()> thread_function,
    absl::string_view name,
    ThreadAttributes attributes) {
  return SpawnThread(std::move(thread_function), name, attributes,
                     /*joinable=*/true);
}

PlatformThread PlatformThread::SpawnDetached(
    std::function<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(
    std::function<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 std::function<void()>([thread_function = std::move(thread_function),
                                 name = std::string(name), attributes] {
        rtc::SetCurrentThreadName(name.c_str());
        SetPriority(attributes.priority);
        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 rtc
