// Copyright 2015 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/shared/starboard/thread_local_storage_internal.h"

#include <functional>
#include <limits>
#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "starboard/common/flat_map.h"
#include "starboard/log.h"
#include "starboard/memory.h"
#include "starboard/once.h"

struct SbThreadLocalKeyPrivate {
  int index;
};

namespace starboard {
namespace shared {

namespace {
TLSKeyManager* s_instance = NULL;
SbOnceControl s_instance_control = SB_ONCE_INITIALIZER;

void InitializeTLS() {
  s_instance = new TLSKeyManager();
}

// RawAllocator uses the SbMemoryAllocateNoReport() and
// SbMemoryDeallocateNoReport() allocation functions. This allows the
// TLSKeyManager to be used with the memory tracking system.
// Without this allocator, the TLSKeyManager could receive an event for memory
// allocation, which will cause memory to be allocated in the map, which will
// generate an event for memory allocation ... which results in an infinite
// loop and a crash.
template <typename T>
class RawAllocator : public std::allocator<T> {
 public:
  typedef typename std::allocator<T>::pointer pointer;
  typedef typename std::allocator<T>::const_pointer const_pointer;
  typedef typename std::allocator<T>::reference reference;
  typedef typename std::allocator<T>::const_reference const_reference;
  typedef typename std::allocator<T>::size_type size_type;
  typedef typename std::allocator<T>::value_type value_type;
  typedef typename std::allocator<T>::difference_type difference_type;

  RawAllocator() {}

  // Constructor used for rebinding
  template <typename U>
  RawAllocator(const RawAllocator<U>& x) {}

  pointer allocate(size_type n,
                   std::allocator<void>::const_pointer hint = NULL) {
    void* ptr = SbMemoryAllocateNoReport(n * sizeof(value_type));
    return static_cast<pointer>(ptr);
  }

  void deallocate(pointer p, size_type n) { SbMemoryDeallocateNoReport(p); }
  template <typename U>
  struct rebind {
    typedef RawAllocator<U> other;
  };
};

// A map of ThreadId -> int. This map is highly concurrent and allows
// access of elements without much contention.
class ConcurrentThreadIdMap {
 public:
  ConcurrentThreadIdMap() {
    // Prime number reduces collisions.
    static const size_t kNumBuckets = 101;
    map_vector_.resize(kNumBuckets);

    for (size_t i = 0; i < map_vector_.size(); ++i) {
      void* memory_block = SbMemoryAllocateNoReport(sizeof(LockedMap));
      map_vector_[i] = new (memory_block) LockedMap;
    }
  }

  ~ConcurrentThreadIdMap() {
    for (size_t i = 0; i < map_vector_.size(); ++i) {
      LockedMap* obj = map_vector_[i];
      obj->~LockedMap();
      SbMemoryDeallocateNoReport(obj);
    }
  }

  bool GetIfExists(SbThreadId key, int* value) const {
    const LockedMap& map = GetBucket(key);
    ScopedLock lock(map.mutex_);
    ThreadIdMap::const_iterator it = map.map_.find(key);
    if (it != map.map_.end()) {
      *value = it->second;
      return true;
    } else {
      return false;
    }
  }

  void Insert(SbThreadId key, int value) {
    LockedMap& map = GetBucket(key);
    ScopedLock lock(map.mutex_);
    map.map_[key] = value;
  }

  void Erase(SbThreadId key) {
    LockedMap& map = GetBucket(key);
    ScopedLock lock(map.mutex_);
    map.map_.erase(key);
  }

 private:
  typedef std::map<SbThreadId,
                   int,
                   std::less<SbThreadId>,
                   RawAllocator<std::pair<const SbThreadId, int> > >
      ThreadIdMap;

  struct LockedMap {
    Mutex mutex_;
    ThreadIdMap map_;
  };

  // Simple hashing function for 32 bit numbers.
  // Based off of Jenkins hash found at this url:
  // https://gist.github.com/badboy/6267743#file-inthash-md
  static size_t Hash(SbThreadId id) {
    static const uint32_t kMagicNum1 = 0x7ed55d16;
    static const uint32_t kMagicNum2 = 0xc761c23c;
    static const uint32_t kMagicNum3 = 0x165667b1;
    static const uint32_t kMagicNum4 = 0xd3a2646c;
    static const uint32_t kMagicNum5 = 0xfd7046c5;
    static const uint32_t kMagicNum6 = 0xfd7046c5;

    static const uint32_t kMagicShift1 = 12;
    static const uint32_t kMagicShift2 = 19;
    static const uint32_t kMagicShift3 = 5;
    static const uint32_t kMagicShift4 = 9;
    static const uint32_t kMagicShift5 = 3;
    static const uint32_t kMagicShift6 = 16;

    uint32_t key = static_cast<uint32_t>(id);
    key = (key + kMagicNum1) + (key << kMagicShift1);
    key = (key ^ kMagicNum2) ^ (key >> kMagicShift2);
    key = (key + kMagicNum3) + (key << kMagicShift3);
    key = (key + kMagicNum4) ^ (key << kMagicShift4);
    key = (key + kMagicNum5) + (key << kMagicShift5);
    key = (key ^ kMagicNum6) ^ (key >> kMagicShift6);
    return static_cast<size_t>(key);
  }

  const LockedMap& GetBucket(SbThreadId key) const {
    size_t bucket_index = Hash(key) % map_vector_.size();
    return *map_vector_[bucket_index];
  }

  LockedMap& GetBucket(SbThreadId key) {
    size_t bucket_index = Hash(key) % map_vector_.size();
    return *map_vector_[bucket_index];
  }

  typedef std::vector<LockedMap*, RawAllocator<LockedMap*> > MapVector;
  MapVector map_vector_;
};

}  // namespace

struct TLSKeyManager::InternalData {
  // These data structures bypass memory reporting. If this wasn't here then
  // any platform using this TLSKeyManager will crash during memory reporting.
  typedef std::vector<KeyRecord, RawAllocator<KeyRecord> > VectorKeyRecord;
  typedef std::vector<int, RawAllocator<int> > VectorInt;
  typedef ConcurrentThreadIdMap ThreadIdMap;

  // Overrides new/delete for InternalData to bypass memory reporting.
  static void* operator new(size_t n) { return SbMemoryAllocateNoReport(n); }
  static void operator delete(void* p) { SbMemoryDeallocateNoReport(p); }

  // The key record tracks all key values among all threads, along with their
  // destructors, if specified.
  VectorKeyRecord key_table_;

  // Tracks all thread IDs that are still available.
  VectorInt available_thread_ids_;

  // This maps Starboard thread IDs to TLS thread ids.
  ThreadIdMap thread_id_map_;
};

TLSKeyManager* TLSKeyManager::Get() {
  SbOnce(&s_instance_control, &InitializeTLS);
  return s_instance;
}

TLSKeyManager::TLSKeyManager() {
  data_.reset(new InternalData);
  data_->available_thread_ids_.reserve(kMaxThreads);
  for (int i = 0; i < kMaxThreads; ++i) {
    data_->available_thread_ids_.push_back(i);
  }
}

SbThreadLocalKey TLSKeyManager::CreateKey(SbThreadLocalDestructor destructor) {
  // Allocate key and bypass the the normal allocator. Otherwise there
  // could be a re-entrant loop that kills the process.
  void* memory_block =
      SbMemoryAllocateNoReport(sizeof(SbThreadLocalKeyPrivate));
  SbThreadLocalKey key = new (memory_block) SbThreadLocalKeyPrivate();

  ScopedLock lock(mutex_);
  key->index = GetUnusedKeyIndex();

  KeyRecord* record = &data_->key_table_[key->index];

  record->destructor = destructor;
  SbMemorySet(record->values, 0, sizeof(record->values));
  record->valid = true;

  return key;
}

void TLSKeyManager::DestroyKey(SbThreadLocalKey key) {
  if (!SbThreadIsValidLocalKey(key)) {
    return;
  }

  ScopedLock lock(mutex_);

  SB_DCHECK(IsKeyActive(key));
  data_->key_table_[key->index].valid = false;

  key.~SbThreadLocalKey();
  SbMemoryDeallocateNoReport(key);
}

bool TLSKeyManager::SetLocalValue(SbThreadLocalKey key, void* value) {
  if (!SbThreadIsValidLocalKey(key)) {
    return false;
  }

  int current_thread_id = GetCurrentThreadId();

  ScopedLock lock(mutex_);

  if (!IsKeyActive(key)) {
    return false;
  }

  data_->key_table_[key->index].values[current_thread_id] = value;

  return true;
}

void* TLSKeyManager::GetLocalValue(SbThreadLocalKey key) {
  if (!SbThreadIsValidLocalKey(key)) {
    return NULL;
  }

  int current_thread_id = GetCurrentThreadId();

  ScopedLock lock(mutex_);

  if (!IsKeyActive(key)) {
    return NULL;
  }

  return data_->key_table_[key->index].values[current_thread_id];
}

void TLSKeyManager::InitializeTLSForThread() {
  int current_thread_id = GetCurrentThreadId();

  ScopedLock lock(mutex_);

  const size_t table_size = data_->key_table_.size();
  for (int i = 0; i < table_size; ++i) {
    KeyRecord* key_record = &data_->key_table_[i];
    if (key_record->valid) {
      key_record->values[current_thread_id] = NULL;
    }
  }
}

void TLSKeyManager::ShutdownTLSForThread() {
  int current_thread_id = GetCurrentThreadId();

  ScopedLock lock(mutex_);

  // Apply the destructors multiple times (4 is the minimum value
  // according to the specifications).  This is necessary if one of
  // the destructors adds new values to the key map.
  for (int d = 0; d < 4; ++d) {
    // Move the map into a new temporary map so that we can iterate
    // through that while the original s_tls_thread_keys may have more
    // values added to it via destructor calls.
    const size_t table_size = data_->key_table_.size();

    for (int i = 0; i < table_size; ++i) {
      KeyRecord* key_record = &data_->key_table_[i];
      if (key_record->valid) {
        void* value = key_record->values[current_thread_id];
        key_record->values[current_thread_id] = NULL;
        SbThreadLocalDestructor destructor = key_record->destructor;

        if (value && destructor) {
          mutex_.Release();
          destructor(value);
          mutex_.Acquire();
        }
      }
    }
  }

  data_->thread_id_map_.Erase(SbThreadGetId());
  data_->available_thread_ids_.push_back(current_thread_id);
}

bool TLSKeyManager::IsKeyActive(SbThreadLocalKey key) {
  return data_->key_table_[key->index].valid;
}

int TLSKeyManager::GetUnusedKeyIndex() {
  const size_t key_table_size = data_->key_table_.size();
  for (int i = 0; i < key_table_size; ++i) {
    if (!data_->key_table_[i].valid) {
      return i;
    }
  }

  data_->key_table_.push_back(KeyRecord());
  data_->key_table_.back().valid = false;

  return data_->key_table_.size() - 1;
}

int TLSKeyManager::GetCurrentThreadId() {
  const SbThreadId thread_id = SbThreadGetId();

  int value = -1;
  if (data_->thread_id_map_.GetIfExists(thread_id, &value)) {
    return value;
  }

  ScopedLock lock(mutex_);

  SB_DCHECK(!data_->available_thread_ids_.empty());
  int thread_tls_id = data_->available_thread_ids_.back();
  data_->available_thread_ids_.pop_back();

  data_->thread_id_map_.Insert(thread_id, thread_tls_id);
  return thread_tls_id;
}

}  // namespace shared
}  // namespace starboard
