// Copyright (c) 2017, 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 RUNTIME_VM_FIXED_CACHE_H_ #define RUNTIME_VM_FIXED_CACHE_H_ #include #include #include "vm/lockers.h" namespace dart { // A simple sorted fixed size Key-Value storage. // // Assumes both Key and Value are default-constructible objects. // // Keys must be comparable with operator<. // // Duplicates are not allowed - check with Lookup before insertion. // template class FixedCache { public: struct Entry { K key; V value; }; FixedCache() : length_(0) {} ~FixedCache() { Clear(); } V* Lookup(K key) { MutexLocker ml(&mutex_); intptr_t i = LowerBound(key); if (i != length_ && pairs_[i].key == key) return &pairs_[i].value; return nullptr; } void Insert(K key, V value) { MutexLocker ml(&mutex_); intptr_t i = LowerBound(key); if (length_ == kCapacity) { length_ = kCapacity - 1; if (i == kCapacity) i = kCapacity - 1; } for (intptr_t j = length_ - 1; j >= i; j--) { pairs_[j + 1] = pairs_[j]; } length_ += 1; pairs_[i].key = key; pairs_[i].value = value; } void Clear() { MutexLocker ml(&mutex_); length_ = 0; } private: intptr_t LowerBound(K key) { intptr_t low = 0, high = length_; while (low != high) { intptr_t mid = low + (high - low) / 2; if (key < pairs_[mid].key) { high = mid; } else if (key > pairs_[mid].key) { low = mid + 1; } else { low = high = mid; } } return low; } // We protect any operation on the [FixedCache] because multiple isolates from // the same [IsolateGroup] can access this cache concurrently (as can the GC // when it clears it). Mutex mutex_; Entry pairs_[kCapacity]; // Sorted array of pairs. intptr_t length_; }; } // namespace dart #endif // RUNTIME_VM_FIXED_CACHE_H_