// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/thread_registry.h"

#include "vm/isolate.h"
#include "vm/lockers.h"

namespace dart {

ThreadRegistry::~ThreadRegistry() {
  // Go over the free thread list and delete the thread objects.
  {
    MonitorLocker ml(threads_lock());
    // At this point the active list should be empty.
    ASSERT(active_list_ == NULL);
    // We have cached the mutator thread, delete it.
    delete mutator_thread_;
    mutator_thread_ = NULL;
    // Now delete all the threads in the free list.
    while (free_list_ != NULL) {
      Thread* thread = free_list_;
      free_list_ = thread->next_;
      delete thread;
    }
  }

  // Delete monitor.
  delete threads_lock_;
}


// Gets a free Thread structure, we special case the mutator thread
// by reusing the cached structure, see comment in 'thread_registry.h'.
Thread* ThreadRegistry::GetFreeThreadLocked(Isolate* isolate, bool is_mutator) {
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  Thread* thread;
  if (is_mutator) {
    if (mutator_thread_ == NULL) {
      mutator_thread_ = GetFromFreelistLocked(isolate);
    }
    thread = mutator_thread_;
  } else {
    thread = GetFromFreelistLocked(isolate);
    ASSERT(thread->api_top_scope() == NULL);
  }
  // Now add this Thread to the active list for the isolate.
  AddToActiveListLocked(thread);
  return thread;
}


void ThreadRegistry::ReturnThreadLocked(bool is_mutator, Thread* thread) {
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  // Remove thread from the active list for the isolate.
  RemoveFromActiveListLocked(thread);
  if (!is_mutator) {
    ReturnToFreelistLocked(thread);
  }
}


void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor,
                                         bool validate_frames) {
  MonitorLocker ml(threads_lock());
  bool mutator_thread_visited = false;
  Thread* thread = active_list_;
  while (thread != NULL) {
    thread->VisitObjectPointers(visitor, validate_frames);
    if (mutator_thread_ == thread) {
      mutator_thread_visited = true;
    }
    thread = thread->next_;
  }
  // Visit mutator thread even if it is not in the active list because of
  // api handles.
  if (!mutator_thread_visited && (mutator_thread_ != NULL)) {
    mutator_thread_->VisitObjectPointers(visitor, validate_frames);
  }
}


void ThreadRegistry::PrepareForGC() {
  MonitorLocker ml(threads_lock());
  Thread* thread = active_list_;
  while (thread != NULL) {
    thread->PrepareForGC();
    thread = thread->next_;
  }
}


void ThreadRegistry::AddToActiveListLocked(Thread* thread) {
  ASSERT(thread != NULL);
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  thread->next_ = active_list_;
  active_list_ = thread;
}


void ThreadRegistry::RemoveFromActiveListLocked(Thread* thread) {
  ASSERT(thread != NULL);
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  Thread* prev = NULL;
  Thread* current = active_list_;
  while (current != NULL) {
    if (current == thread) {
      if (prev == NULL) {
        active_list_ = current->next_;
      } else {
        prev->next_ = current->next_;
      }
      break;
    }
    prev = current;
    current = current->next_;
  }
}


Thread* ThreadRegistry::GetFromFreelistLocked(Isolate* isolate) {
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  Thread* thread = NULL;
  // Get thread structure from free list or create a new one.
  if (free_list_ == NULL) {
    thread = new Thread(isolate);
  } else {
    thread = free_list_;
    free_list_ = thread->next_;
  }
  return thread;
}

void ThreadRegistry::ReturnToFreelistLocked(Thread* thread) {
  ASSERT(thread != NULL);
  ASSERT(thread->os_thread_ == NULL);
  ASSERT(thread->isolate_ == NULL);
  ASSERT(thread->heap_ == NULL);
  ASSERT(threads_lock()->IsOwnedByCurrentThread());
  // Add thread to the free list.
  thread->next_ = free_list_;
  free_list_ = thread;
}

}  // namespace dart
