/*
 * Copyright 2016 Google Inc. 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 NB_THREAD_LOCAL_OBJECT_H_
#define NB_THREAD_LOCAL_OBJECT_H_

#include <set>

#include "starboard/common/log.h"
#include "starboard/common/mutex.h"
#include "starboard/configuration.h"
#include "starboard/thread.h"

namespace nb {

// Like base::ThreadLocalPointer<T> but destroys objects. This is important
// for using ThreadLocalObjects that aren't tied to a singleton, or for
// access by threads which will call join().
//
// FEATURE COMPARISON TABLE:
//                         |  Thread Join       | Container Destroyed
//   ------------------------------------------------------------------
//   ThreadLocalPointer<T> | LEAKS              | LEAKS
//   ThreadLocalObject<T>  | Object Destroyed   | Objects Destroyed
//
// EXAMPLE:
//  ThreadLocalObject<std::map<std::string, int> > map_tls;
//  Map* map = map_tls->GetOrCreate();
//  (*map)["my string"] = 15;
//  Thread t = new Thread(&map_tls);
//  t->start();
//  // t creates it's own thread local map.
//  t->join();  // Make sure that thread joins before map_tls is destroyed!
//
// OBJECT DESTRUCTION:
//   There are two ways for an object to be destroyed by the ThreadLocalObject.
//   The first way is via a thread join. In this case only the object
//   associated with the thread is deleted.
//   The second way an object is destroyed is by the ThreadLocalObject
//   container to be destroyed, in this case ALL thread local objects are
//   destroyed.
//
// PERFORMANCE:
//   ThreadLocalObject is fast for the Get() function if the object has
//   has already been created, requiring one extra pointer dereference
//   over ThreadLocalPointer<T>.
template <typename Type>
class ThreadLocalObject {
 public:
  ThreadLocalObject() : slot_() {
    slot_ = SbThreadCreateLocalKey(DeleteEntry);
    SB_DCHECK(kSbThreadLocalKeyInvalid != slot_);
    constructing_thread_id_ = SbThreadGetId();
  }

  // Enables destruction by any other thread. Otherwise, the class instance
  // will warn when a different thread than the constructing destroys this.
  void EnableDestructionByAnyThread() {
    constructing_thread_id_ = kSbThreadInvalidId;
  }

  // Thread Local Objects are destroyed after this call.
  ~ThreadLocalObject() {
    CheckCurrentThreadAllowedToDestruct();
    if (SB_DLOG_IS_ON(FATAL)) {
      SB_DCHECK(entry_set_.size() < 2)
          << "Logic error: Some threads may still be accessing the objects "
          << "that are about to be destroyed. Only one object is expected "
          << "and that should be for the main thread. The caller should "
          << "ensure that other threads that access this object are"
          << " externally synchronized.";
    }
    // No locking is done because the entries should not be accessed by
    // different threads while this object is shutting down. If access is
    // occuring then the caller has a race condition, external to this class.
    typedef typename Set::iterator Iter;
    for (Iter it = entry_set_.begin(); it != entry_set_.end(); ++it) {
      Entry* entry = *it;
      SB_DCHECK(entry->owner_ == this);
      delete entry->ptr_;
      delete entry;
    }

    // Cleanup the thread local key.
    SbThreadDestroyLocalKey(slot_);
  }

  // Warns if there is a misuse of this object.
  void CheckCurrentThreadAllowedToDestruct() const {
    if (kSbThreadInvalidId == constructing_thread_id_) {
      return;  // EnableDestructionByAnyThread() called.
    }
    const SbThreadId curr_thread_id = SbThreadGetId();
    if (curr_thread_id == constructing_thread_id_) {
      return;  // Same thread that constructed this.
    }

    if (SB_DLOG_IS_ON(FATAL)) {
      SB_DCHECK(false) << "ThreadLocalObject<T> was created in thread "
                       << constructing_thread_id_ << "\nbut was destroyed by "
                       << curr_thread_id
                       << ". If this is intentional then call "
                       << "EnableDestructionByAnyThread() to silence this "
                       << "warning.";
    }
  }

  // Either returns the created pointer for the current thread, or otherwise
  // constructs the object using the default constructor and returns it.
  Type* GetOrCreate() {
    Type* object = GetIfExists();
    if (!object) {  // create object.
      object = new Type();
      Entry* entry = new Entry(this, object);
      // Insert into the set of tls entries.
      // Performance: Its assumed that creation of objects is much less
      // frequent than getting an object.
      {
        starboard::ScopedLock lock(entry_set_mutex_);
        entry_set_.insert(entry);
      }
      SbThreadSetLocalValue(slot_, entry);
    }
    return object;
  }

  template <typename ConstructorArg>
  Type* GetOrCreate(const ConstructorArg& arg) {
    Type* object = GetIfExists();
    if (!object) {  // create object.
      object = new Type(arg);
      Entry* entry = new Entry(this, object);
      // Insert into the set of tls entries.
      // Performance: Its assumed that creation of objects is much less
      // frequent than getting an object.
      {
        starboard::ScopedLock lock(entry_set_mutex_);
        entry_set_.insert(entry);
      }
      SbThreadSetLocalValue(slot_, entry);
    }
    return object;
  }

  // Returns the pointer if it exists in the current thread, otherwise NULL.
  Type* GetIfExists() const {
    Entry* entry = GetEntryIfExists();
    if (!entry) {
      return NULL;
    }
    return entry->ptr_;
  }

  // Releases ownership of the pointer FROM THE CURRENT THREAD.
  // The caller has responsibility to make sure that the pointer is destroyed.
  Type* Release() {
    if (Entry* entry = GetEntryIfExists()) {
      // The entry will no longer run it's destructor on thread join.
      SbThreadSetLocalValue(slot_, NULL);  // NULL out pointer for TLS.
      Type* object = entry->ptr_;
      RemoveEntry(entry);
      return object;
    } else {
      return NULL;
    }
  }

 private:
  struct Entry {
    Entry(ThreadLocalObject* own, Type* ptr) : owner_(own), ptr_(ptr) {}
    ~Entry() {
      ptr_ = NULL;
      owner_ = NULL;
    }
    ThreadLocalObject* owner_;
    Type* ptr_;
  };

  // Deletes the TLSEntry.
  static void DeleteEntry(void* ptr) {
    if (!ptr) {
      SB_NOTREACHED();
      return;
    }
    Entry* entry = reinterpret_cast<Entry*>(ptr);
    ThreadLocalObject* tls = entry->owner_;
    Type* object = entry->ptr_;
    if (tls) {
      tls->RemoveEntry(entry);
    }
    delete object;
  }

  void RemoveEntry(Entry* entry) {
    {
      starboard::ScopedLock lock(entry_set_mutex_);
      entry_set_.erase(entry);
    }
    delete entry;
  }

  Entry* GetEntryIfExists() const {
    void* ptr = SbThreadGetLocalValue(slot_);
    Entry* entry = static_cast<Entry*>(ptr);
    return entry;
  }

  typedef std::set<Entry*> Set;
  // Allows GetIfExists() to be const.
  mutable SbThreadLocalKey slot_;
  // entry_set_ contains all the outstanding entries for the thread local
  // objects that have been created.
  Set entry_set_;
  mutable starboard::Mutex entry_set_mutex_;
  // Used to warn when there is a mismatch between thread that constructed and
  // thread that destroyed this object.
  SbThreadId constructing_thread_id_;

  ThreadLocalObject<Type>(const ThreadLocalObject<Type>&) = delete;
  void operator=(const ThreadLocalObject<Type>&) = delete;
};

}  // namespace nb

#endif  // NB_THREAD_LOCAL_OBJECT_H_
