/*
 * 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 BASE_THREADING_THREAD_LOCAL_OBJECT_H_
#define BASE_THREADING_THREAD_LOCAL_OBJECT_H_

#include <set>

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

namespace base {

// 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();
    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;
  }

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

#endif  // BASE_THREADING_THREAD_LOCAL_H_
