/*
 * 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_;

  SB_DISALLOW_COPY_AND_ASSIGN(ThreadLocalObject<Type>);
};

}  // namespace nb

#endif  // NB_THREAD_LOCAL_OBJECT_H_
