// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "starboard/thread.h"

#include <process.h>
#include <memory>

#include "starboard/common/log.h"
#include "starboard/once.h"
#include "starboard/shared/win32/error_utils.h"
#include "starboard/shared/win32/thread_private.h"
#include "starboard/shared/win32/wchar_utils.h"

namespace sbwin32 = starboard::shared::win32;

using sbwin32::DebugLogWinError;
using sbwin32::GetThreadSubsystemSingleton;
using sbwin32::SbThreadPrivate;
using sbwin32::ThreadSubsystemSingleton;
using sbwin32::wchar_tToUTF8;

namespace {

void ResetWinError() {
  SetLastError(0);
}

class ThreadCreateInfo {
 public:
  SbThreadPrivate thread_private_;
  SbThreadEntryPoint entry_point_;
  void* user_context_;
  std::string name_;
};

int RunThreadLocalDestructors(ThreadSubsystemSingleton* singleton) {
  int num_destructors_called = 0;

  for (auto it = singleton->thread_local_keys_.begin();
       it != singleton->thread_local_keys_.end();) {
    auto curr_it = it++;

    if (!curr_it->second->destructor) {
      continue;
    }
    auto key = curr_it->second;
    void* entry = SbThreadGetLocalValue(key);
    if (!entry) {
      continue;
    }
    SbThreadSetLocalValue(key, nullptr);
    ++num_destructors_called;
    curr_it->second->destructor(entry);
  }
  return num_destructors_called;
}

int CountTlsObjectsRemaining(ThreadSubsystemSingleton* singleton) {
  int num_objects_remain = 0;
  for (auto it = singleton->thread_local_keys_.begin();
       it != singleton->thread_local_keys_.end(); ++it) {
    if (!it->second->destructor) {
      continue;
    }
    auto key = it->second;
    void* entry = SbThreadGetLocalValue(key);
    if (!entry) {
      continue;
    }
    ++num_objects_remain;
  }
  return num_objects_remain;
}

void CallThreadLocalDestructorsMultipleTimes() {
  // The number of passes conforms to the base_unittests. This is useful for
  // destructors that insert new objects into thread local storage. These
  // objects then need to be destroyed as well in subsequent passes. The total
  // number of passes is 4, which is one more than what base_unittest tests
  // for.
  const int kNumDestructorPasses = 4;

  ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
  int num_tls_objects_remaining = 0;
  // TODO note that the implementation below holds a global lock
  // while processing TLS destructors on thread exit. This could
  // be a bottleneck in some scenarios. A lockless approach may be preferable.
  SbMutexAcquire(&singleton->mutex_);

  for (int i = 0; i < kNumDestructorPasses; ++i) {
    // Run through each destructor and call it.
    const int num_destructors_called = RunThreadLocalDestructors(singleton);
    if (0 == num_destructors_called) {
      break;  // No more destructors to call.
    }
  }
  num_tls_objects_remaining = CountTlsObjectsRemaining(singleton);
  SbMutexRelease(&singleton->mutex_);

  SB_DCHECK(num_tls_objects_remaining == 0) << "Dangling objects in TLS exist.";
}

unsigned ThreadTrampoline(void* thread_create_info_context) {
  std::unique_ptr<ThreadCreateInfo> info(
      static_cast<ThreadCreateInfo*>(thread_create_info_context));

  ThreadSubsystemSingleton* singleton = GetThreadSubsystemSingleton();
  SbThreadSetLocalValue(singleton->thread_private_key_, &info->thread_private_);
  SbThreadSetName(info->name_.c_str());

  void* result = info->entry_point_(info->user_context_);

  CallThreadLocalDestructorsMultipleTimes();

  SbMutexAcquire(&info->thread_private_.mutex_);
  info->thread_private_.result_ = result;
  info->thread_private_.result_is_valid_ = true;
  SbConditionVariableSignal(&info->thread_private_.condition_);
  while (info->thread_private_.wait_for_join_) {
    SbConditionVariableWait(&info->thread_private_.condition_,
                            &info->thread_private_.mutex_);
  }
  SbMutexRelease(&info->thread_private_.mutex_);

  return 0;
}

int SbThreadPriorityToWin32Priority(SbThreadPriority priority) {
  switch (priority) {
    case kSbThreadPriorityLowest:
      return THREAD_PRIORITY_LOWEST;
    case kSbThreadPriorityLow:
      return THREAD_PRIORITY_BELOW_NORMAL;
    case kSbThreadPriorityNormal:
    case kSbThreadNoPriority:
      return THREAD_PRIORITY_NORMAL;
    case kSbThreadPriorityHigh:
      return THREAD_PRIORITY_ABOVE_NORMAL;
    case kSbThreadPriorityHighest:
      return THREAD_PRIORITY_HIGHEST;
    case kSbThreadPriorityRealTime:
      return THREAD_PRIORITY_TIME_CRITICAL;
  }
  SB_NOTREACHED() << "Invalid priority " << priority;
  return 0;
}
}  // namespace

// Note that SetThreadAffinityMask() is not available on some
// platforms (eg UWP). If it's necessary for a non-UWP platform,
// please fork this implementation for UWP.
SbThread SbThreadCreate(int64_t stack_size,
                        SbThreadPriority priority,
                        SbThreadAffinity affinity,
                        bool joinable,
                        const char* name,
                        SbThreadEntryPoint entry_point,
                        void* context) {
  if (entry_point == NULL) {
    return kSbThreadInvalid;
  }
  ThreadCreateInfo* info = new ThreadCreateInfo();

  info->entry_point_ = entry_point;
  info->user_context_ = context;
  info->thread_private_.wait_for_join_ = joinable;
  if (name) {
    info->name_ = name;
  }

  // Create the thread suspended, and then resume once ThreadCreateInfo::handle_
  // has been set, so that it's always valid in the ThreadCreateInfo
  // destructor.
  uintptr_t handle =
      _beginthreadex(NULL, static_cast<unsigned int>(stack_size),
                     ThreadTrampoline, info, CREATE_SUSPENDED, NULL);
  SB_DCHECK(handle);
  info->thread_private_.handle_ = reinterpret_cast<HANDLE>(handle);
  ResetWinError();
  if (priority != kSbThreadNoPriority &&
      !SetThreadPriority(info->thread_private_.handle_,
                         SbThreadPriorityToWin32Priority(priority)) &&
      !GetLastError()) {
    SB_LOG(ERROR) << "Failed to set priority for thread " << (name ? name : "")
                  << " to " << priority;
    DebugLogWinError();
  }

  ResumeThread(info->thread_private_.handle_);

  return &info->thread_private_;
}
