| Index: runtime/vm/thread_registry.h
|
| diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..bbabea2225807dc99440503e4703eb9dc34d3aca
|
| --- /dev/null
|
| +++ b/runtime/vm/thread_registry.h
|
| @@ -0,0 +1,105 @@
|
| +// 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/thread.h"
|
| +
|
| +namespace dart {
|
| +
|
| +// Unordered collection of threads relating to a particular isolate.
|
| +class ThreadRegistry {
|
| + public:
|
| + ThreadRegistry() : mutex_(), entries_() {}
|
| +
|
| + bool RestoreStateTo(Thread* thread, Thread::State* state) {
|
| + MutexLocker ml(&mutex_);
|
| + 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) {
|
| + MutexLocker ml(&mutex_);
|
| + Entry* entry = FindEntry(thread);
|
| + ASSERT(entry != NULL);
|
| + ASSERT(entry->scheduled);
|
| + entry->scheduled = false;
|
| + entry->state = state;
|
| + }
|
| +
|
| + bool Contains(Thread* thread) {
|
| + MutexLocker ml(&mutex_);
|
| + return (FindEntry(thread) != NULL);
|
| + }
|
| +
|
| + void VisitObjectPointers(ObjectPointerVisitor* visitor) {
|
| + MutexLocker ml(&mutex_);
|
| + for (int i = 0; i < entries_.length(); ++i) {
|
| + const Entry& entry = entries_[i];
|
| + Zone* zone = entry.scheduled ? entry.thread->zone() : entry.state.zone;
|
| + if (zone != NULL) {
|
| + zone->VisitObjectPointers(visitor);
|
| + }
|
| + }
|
| + }
|
| +
|
| + private:
|
| + struct Entry {
|
| + Thread* thread;
|
| + bool scheduled;
|
| + Thread::State state;
|
| + };
|
| +
|
| + // Returns Entry corresponding to thread in registry or NULL.
|
| + // Note: Lock should be taken before this function is called.
|
| + Entry* FindEntry(Thread* thread) {
|
| + DEBUG_ASSERT(mutex_.IsOwnedByCurrentThread());
|
| + for (int i = 0; i < entries_.length(); ++i) {
|
| + if (entries_[i].thread == thread) {
|
| + return &entries_[i];
|
| + }
|
| + }
|
| + return NULL;
|
| + }
|
| +
|
| + Mutex mutex_;
|
| + MallocGrowableArray<Entry> entries_;
|
| +
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ThreadRegistry);
|
| +};
|
| +
|
| +} // namespace dart
|
| +
|
| +#endif // VM_THREAD_REGISTRY_H_
|
|
|