// 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.

#ifndef VM_THREAD_REGISTRY_H_
#define VM_THREAD_REGISTRY_H_

#include "vm/globals.h"
#include "vm/growable_array.h"
#include "vm/isolate.h"
#include "vm/lockers.h"
#include "vm/stack_frame.h"
#include "vm/thread.h"

namespace dart {

// Unordered collection of threads relating to a particular isolate.
class ThreadRegistry {
 public:
  ThreadRegistry()
      : monitor_(new Monitor()),
        entries_(),
        in_rendezvous_(false),
        remaining_(0),
        round_(0) {}

  ~ThreadRegistry();

  // Bring all threads in this isolate to a safepoint. The caller is
  // expected to be implicitly at a safepoint. The threads will wait
  // until ResumeAllThreads is called. First participates in any
  // already pending rendezvous requested by another thread. Any
  // thread that tries to enter this isolate during rendezvous will
  // wait in RestoreStateTo. Nesting is not supported: the caller must
  // call ResumeAllThreads before making further calls to
  // SafepointThreads.
  void SafepointThreads();

  // Unblocks all threads participating in the rendezvous that was organized
  // by a prior call to SafepointThreads.
  // TODO(koda): Consider adding a scope helper to avoid omitting this call.
  void ResumeAllThreads();

  // Indicate that the current thread is at a safepoint, and offer to wait for
  // any pending rendezvous request (if none, returns immediately).
  void CheckSafepoint() {
    MonitorLocker ml(monitor_);
    CheckSafepointLocked();
  }

  bool RestoreStateTo(Thread* thread, Thread::State* state,
                      bool bypass_safepoint) {
    MonitorLocker ml(monitor_);
    // Wait for any rendezvous in progress.
    while (!bypass_safepoint && in_rendezvous_) {
      ml.Wait(Monitor::kNoTimeout);
    }
    Entry* entry = FindEntry(thread);
    if (entry != NULL) {
      Thread::State st = entry->state;
      // TODO(koda): Support same thread re-entering same isolate with
      // Dart frames in between. For now, just assert it doesn't happen.
      if (st.top_exit_frame_info != thread->top_exit_frame_info()) {
        ASSERT(thread->top_exit_frame_info() == 0 ||
               thread->top_exit_frame_info() > st.top_exit_frame_info);
      }
      ASSERT(!entry->scheduled);
      entry->scheduled = true;
#if defined(DEBUG)
      // State field is not in use, so zap it.
      memset(&entry->state, 0xda, sizeof(entry->state));
#endif
      *state = st;
      return true;
    }
    Entry new_entry;
    new_entry.thread = thread;
    new_entry.scheduled = true;
#if defined(DEBUG)
    // State field is not in use, so zap it.
    memset(&new_entry.state, 0xda, sizeof(new_entry.state));
#endif
    entries_.Add(new_entry);
    return false;
  }

  void SaveStateFrom(Thread* thread, const Thread::State& state,
                     bool bypass_safepoint) {
    MonitorLocker ml(monitor_);
    Entry* entry = FindEntry(thread);
    ASSERT(entry != NULL);
    ASSERT(entry->scheduled);
    entry->scheduled = false;
    entry->state = state;
    if (!bypass_safepoint && in_rendezvous_) {
      // Don't wait for this thread.
      ASSERT(remaining_ > 0);
      if (--remaining_ == 0) {
        ml.NotifyAll();
      }
    }
  }

  bool Contains(Thread* thread) {
    MonitorLocker ml(monitor_);
    return (FindEntry(thread) != NULL);
  }

  void CheckNotScheduled(Isolate* isolate) {
    MonitorLocker ml(monitor_);
    for (int i = 0; i < entries_.length(); ++i) {
      const Entry& entry = entries_[i];
      if (entry.scheduled) {
        FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n",
               isolate,
               entry.thread,
               entry.thread->isolate());
      }
    }
  }

  void VisitObjectPointers(ObjectPointerVisitor* visitor,
                           bool validate_frames) {
    MonitorLocker ml(monitor_);
    for (int i = 0; i < entries_.length(); ++i) {
      const Entry& entry = entries_[i];
      const Thread::State& state =
          entry.scheduled ? entry.thread->state_ : entry.state;
      if (state.zone != NULL) {
        state.zone->VisitObjectPointers(visitor);
      }
      // Iterate over all the stack frames and visit objects on the stack.
      StackFrameIterator frames_iterator(state.top_exit_frame_info,
                                         validate_frames);
      StackFrame* frame = frames_iterator.NextFrame();
      while (frame != NULL) {
        frame->VisitObjectPointers(visitor);
        frame = frames_iterator.NextFrame();
      }
    }
  }

  void PruneThread(Thread* thread);

  void ReclaimTimelineBlocks();

  struct Entry {
    // NOTE: |thread| is deleted automatically when the thread exits.
    // In other words, it is not safe to dereference |thread| unless you are on
    // the thread itself.
    Thread* thread;
    bool scheduled;
    Thread::State state;
  };

  class EntryIterator {
   public:
    explicit EntryIterator(ThreadRegistry* registry);
    ~EntryIterator();

    // Returns false when there are no more entries.
    bool HasNext() const;

    // Returns the next entry and moves forward.
    const Entry& Next();

   private:
    void Reset(ThreadRegistry* registry);

    intptr_t index_;
    ThreadRegistry* registry_;
  };

 private:
  // Returns Entry corresponding to thread in registry or NULL.
  // Note: Lock should be taken before this function is called.
  // TODO(koda): Add method Monitor::IsOwnedByCurrentThread.
  Entry* FindEntry(Thread* thread) {
    for (int i = 0; i < entries_.length(); ++i) {
      if (entries_[i].thread == thread) {
        return &entries_[i];
      }
    }
    return NULL;
  }

  // NOTE: Lock should be taken before this function is called.
  void ReclaimTimelineBlockLocked(Entry* entry);

  // Note: Lock should be taken before this function is called.
  void CheckSafepointLocked();

  // Returns the number threads that are scheduled on this isolate.
  // Note: Lock should be taken before this function is called.
  intptr_t CountScheduledLocked();

  Monitor* monitor_;  // All access is synchronized through this monitor.
  MallocGrowableArray<Entry> entries_;

  // Safepoint rendezvous state.
  bool in_rendezvous_;    // A safepoint rendezvous request is in progress.
  intptr_t remaining_;    // Number of threads yet to reach their safepoint.
  int64_t round_;         // Counter, to prevent missing updates to remaining_
                          // (see comments in CheckSafepointLocked).

  DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
};

}  // namespace dart

#endif  // VM_THREAD_REGISTRY_H_
