blob: 91b70c5061bc389e3c9cf3cf04493133a57f6b7d [file] [log] [blame]
// Copyright (c) 2017 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 CONTENT_RENDERER_MEDIA_WEBRTC_TWO_KEYS_MAP_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_TWO_KEYS_MAP_H_
#include <map>
#include <memory>
#include <utility>
#include "base/logging.h"
namespace content {
// A map with up to two keys per entry. An element is inserted with a key, this
// is the primary key. A secondary key can optionally be set to the same entry
// and it may be set at a later point in time than the element was inserted. For
// lookup and erasure both keys can be used.
//
// This was designed to assist the implementation of adapter maps. The adapters
// are the glue between the blink and webrtc layer objects. The adapter maps
// keep track of which blink and webrtc layer objects have which associated
// adapter. This requires two keys per adapter entry: something that can be used
// for lookup based on a webrtc layer object and something that can be used for
// lookup based on a blink layer object. The primary key is based on the
// webrtc/blink object that was used to create the adapter and the secondary key
// is based on the resulting blink/webrtc object after the adapter has been
// initialized.
template <typename PrimaryKey, typename SecondaryKey, typename Value>
class TwoKeysAdapterMap {
public:
// Maps the primary key to the value, increasing |PrimarySize| by one and
// allowing lookup of the value based on primary key. Returns a pointer to the
// value in the map, the pointer is valid for as long as the value is in the
// map. There must not already exist a mapping for this primary key, in other
// words |!FindByPrimary(primary)| must hold.
Value* Insert(PrimaryKey primary, Value value) {
DCHECK(entries_by_primary_.find(primary) == entries_by_primary_.end());
auto it = entries_by_primary_
.insert(std::make_pair(
std::move(primary),
std::unique_ptr<Entry>(new Entry(std::move(value)))))
.first;
it->second->primary_it = it;
return &it->second->value;
}
// Maps the secondary key to the value mapped by the primary key, increasing
// |SecondarySize| by one and allowing lookup of the value based on secondary
// key.
// There must exist a mapping for this primary key and there must not already
// exist a mapping for this secondary key, in other words
// |FindByPrimary(primary) && !FindBySecondary(secondary)| must hold.
void SetSecondaryKey(const PrimaryKey& primary, SecondaryKey secondary) {
auto it = entries_by_primary_.find(primary);
DCHECK(it != entries_by_primary_.end());
DCHECK(entries_by_secondary_.find(secondary) ==
entries_by_secondary_.end());
Entry* entry = it->second.get();
entry->secondary_it =
entries_by_secondary_
.insert(std::make_pair(std::move(secondary), entry))
.first;
}
// Returns a pointer to the value mapped by the primary key, or null if the
// primary key is not mapped to any value. The pointer is valid for as long as
// the value is in the map.
Value* FindByPrimary(const PrimaryKey& primary) const {
auto it = entries_by_primary_.find(primary);
if (it == entries_by_primary_.end())
return nullptr;
return &it->second->value;
}
// Returns a pointer to the value mapped by the secondary key, or null if the
// secondary key is not mapped to any value. The pointer is valid for as long
// as the value is in the map.
Value* FindBySecondary(const SecondaryKey& secondary) const {
auto it = entries_by_secondary_.find(secondary);
if (it == entries_by_secondary_.end())
return nullptr;
return &it->second->value;
}
// Erases the value associated with the primary key, removing the mapping of
// of its primary and secondary key, if it had one. Returns true on removal or
// false if there was no value associated with the primary key.
bool EraseByPrimary(const PrimaryKey& primary) {
auto primary_it = entries_by_primary_.find(primary);
if (primary_it == entries_by_primary_.end())
return false;
if (primary_it->second->secondary_it != entries_by_secondary_.end())
entries_by_secondary_.erase(primary_it->second->secondary_it);
entries_by_primary_.erase(primary_it);
return true;
}
// Erases the value associated with the secondary key, removing the mapping of
// of both its primary and secondary keys. Returns true on removal or false if
// there was no value associated with the secondary key.
bool EraseBySecondary(const SecondaryKey& secondary) {
auto secondary_it = entries_by_secondary_.find(secondary);
if (secondary_it == entries_by_secondary_.end())
return false;
entries_by_primary_.erase(secondary_it->second->primary_it);
entries_by_secondary_.erase(secondary_it);
return true;
}
// The number of elements in the map.
size_t PrimarySize() const { return entries_by_primary_.size(); }
// The number of elements in the map which have secondary keys.
size_t SecondarySize() const { return entries_by_secondary_.size(); }
bool empty() const { return entries_by_primary_.empty(); }
private:
struct Entry {
Entry(Value value) : value(std::move(value)) {}
Value value;
typename std::map<PrimaryKey, std::unique_ptr<Entry>>::iterator primary_it;
typename std::map<SecondaryKey, Entry*>::iterator secondary_it;
};
typename std::map<PrimaryKey, std::unique_ptr<Entry>> entries_by_primary_;
typename std::map<SecondaryKey, Entry*> entries_by_secondary_;
};
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBRTC_TWO_KEYS_MAP_H_