// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_WEAK_IDENTIFIER_MAP_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_WEAK_IDENTIFIER_MAP_H_ #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" namespace blink { // TODO(sof): WeakIdentifierMap<> belongs (out) in wtf/, but // cannot until GarbageCollected<> can be used from WTF. template class WeakIdentifierMapBase { USING_FAST_MALLOC(WeakIdentifierMapBase); protected: using ObjectToIdentifier = HashMap; using IdentifierToObject = HashMap; ObjectToIdentifier object_to_identifier_; IdentifierToObject identifier_to_object_; }; template class WeakIdentifierMapBase : public GarbageCollected> { public: void Trace(Visitor* visitor) { visitor->Trace(object_to_identifier_); visitor->Trace(identifier_to_object_); } protected: using ObjectToIdentifier = HeapHashMap, IdentifierType>; using IdentifierToObject = HeapHashMap>; ObjectToIdentifier object_to_identifier_; IdentifierToObject identifier_to_object_; }; template class WeakIdentifierMap final : public WeakIdentifierMapBase::value> { public: static IdentifierType Identifier(T* object) { IdentifierType result = Instance().object_to_identifier_.at(object); if (WTF::IsHashTraitsEmptyValue>(result)) { result = Next(); Instance().Put(object, result); } return result; } WeakIdentifierMap() = default; static T* Lookup(IdentifierType identifier) { return Instance().identifier_to_object_.at(identifier); } static void NotifyObjectDestroyed(T* object) { Instance().ObjectDestroyed(object); } private: static WeakIdentifierMap& Instance(); static IdentifierType Next() { static IdentifierType last_id = 0; return ++last_id; } void Put(T* object, IdentifierType identifier) { DCHECK(object && !this->object_to_identifier_.Contains(object)); this->object_to_identifier_.Set(object, identifier); this->identifier_to_object_.Set(identifier, object); } void ObjectDestroyed(T* object) { IdentifierType identifier = this->object_to_identifier_.Take(object); if (!WTF::IsHashTraitsEmptyValue>(identifier)) this->identifier_to_object_.erase(identifier); } }; #define DECLARE_WEAK_IDENTIFIER_MAP(T, ...) \ template <> \ WeakIdentifierMap& \ WeakIdentifierMap::Instance(); \ extern template class WeakIdentifierMap; #define DEFINE_WEAK_IDENTIFIER_MAP(T, ...) \ template class WeakIdentifierMap; \ template <> \ WeakIdentifierMap& \ WeakIdentifierMap::Instance() { \ using RefType = WeakIdentifierMap; \ DEFINE_STATIC_LOCAL( \ Persistent, map_instance, \ (MakeGarbageCollected>())); \ return *map_instance; \ } } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_WEAK_IDENTIFIER_MAP_H_