// 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.

#ifndef STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_
#define STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_

#include <windows.h>

#include <map>
#include <string>

#include "starboard/common/condition_variable.h"
#include "starboard/common/mutex.h"
#include "starboard/common/once.h"
#include "starboard/shared/internal_only.h"
#include "starboard/thread.h"

#define kSbThreadLocalKeyInvalid (SbThreadLocalKey) NULL

typedef void (*SbThreadLocalDestructor)(void* value);

struct SbThreadLocalKeyPrivate {
  DWORD tls_index;
  SbThreadLocalDestructor destructor;
};

typedef SbThreadLocalKeyPrivate* SbThreadLocalKey;

static inline bool SbThreadIsValidLocalKey(SbThreadLocalKey key) {
  return key != kSbThreadLocalKeyInvalid;
}

namespace starboard {
namespace shared {
namespace win32 {

class ThreadSubsystemSingleton;

SbThreadLocalKey ThreadCreateLocalKey(SbThreadLocalDestructor destructor);
void ThreadDestroyLocalKey(SbThreadLocalKey key);
void* ThreadGetLocalValue(SbThreadLocalKey key);
bool ThreadSetLocalValue(SbThreadLocalKey key, void* value);

// Creates a SbThreadLocalKey given a ThreadSubsystemSingleton. Used
// to create the first SbThreadLocalKey.
SbThreadLocalKey SbThreadCreateLocalKeyInternal(
    SbThreadLocalDestructor destructor,
    ThreadSubsystemSingleton* singleton);

// Singleton state for the thread subsystem.
class ThreadSubsystemSingleton {
 public:
  ThreadSubsystemSingleton()
      : mutex_(PTHREAD_MUTEX_INITIALIZER),
        thread_private_key_(SbThreadCreateLocalKeyInternal(NULL, this)) {}
  // This mutex protects all class members
  pthread_mutex_t mutex_;
  // Allocated thread_local_keys. Note that std::map is used
  // so that elements can be deleted without triggering an allocation.
  std::map<DWORD, SbThreadLocalKeyPrivate*> thread_local_keys_;
  // Thread-local key for the thread's SbThreadPrivate
  SbThreadLocalKey thread_private_key_;
};

// Obtains the ThreadsSubsystemSingleton();
ThreadSubsystemSingleton* GetThreadSubsystemSingleton();

// Registers the main thread. setting it's SbThreadPrivate*
void RegisterMainThread();

// Private thread state, stored in thread local storage and
// cleaned up when thread exits.
class SbThreadPrivate {
 public:
  SbThreadPrivate()
      : mutex_(PTHREAD_MUTEX_INITIALIZER),
        condition_(PTHREAD_COND_INITIALIZER),
        handle_(NULL),
        result_(NULL),
        wait_for_join_(false),
        result_is_valid_(false) {}

  ~SbThreadPrivate() {
    if (handle_) {
      CloseHandle(handle_);
    }

    pthread_mutex_destroy(&mutex_);
    pthread_cond_destroy(&condition_);
  }

  // This mutex protects all class members
  pthread_mutex_t mutex_;
  pthread_cond_t condition_;
  std::string name_;
  HANDLE handle_;
  // The result of the thread. The return value of SbThreadEntryPoint
  // to return to SbThreadJoin.
  void* result_;
  // True if a thread must wait to be joined before completely exiting.
  // Changes to this must signal |condition_|.
  bool wait_for_join_;
  // True if |result_| is valid (the thread has completed and is waiting
  // to exit). Changes to this must signal |condition_|.
  bool result_is_valid_;
};

// Obtains the current thread's SbThreadPrivate* from thread-local storage.
SbThreadPrivate* GetCurrentSbThreadPrivate();

typedef void* (*SbThreadEntryPoint)(void* context);

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

}  // namespace win32
}  // namespace shared
}  // namespace starboard

#endif  // STARBOARD_SHARED_WIN32_THREAD_PRIVATE_H_
