safe_map.h revision b19955d3c8fbd9588f7e17299e559d02938154b6
1748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes/*
2748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * Copyright (C) 2012 The Android Open Source Project
3748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes *
4748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
5748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * you may not use this file except in compliance with the License.
6748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * You may obtain a copy of the License at
7748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes *
8748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
9748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes *
10748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * Unless required by applicable law or agreed to in writing, software
11748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
12748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * See the License for the specific language governing permissions and
14748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes * limitations under the License.
15748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes */
16748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes
17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_SAFE_MAP_H_
18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_SAFE_MAP_H_
19a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
20a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include <map>
210a9dc05e704bfd033bac2aa38a4fc6f6b8e6cf93Mathieu Chartier#include <memory>
22a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
2307ed66b5ae659c452cbe1ab20c3dbf1d6f546461Elliott Hughes#include "base/logging.h"
24a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
25a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughesnamespace art {
26a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
27a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes// Equivalent to std::map, but without operator[] and its bug-prone semantics (in particular,
28a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes// the implicit insertion of a default-constructed value on failed lookups).
290a9dc05e704bfd033bac2aa38a4fc6f6b8e6cf93Mathieu Chartiertemplate <typename K, typename V, typename Comparator = std::less<K>,
30700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers          typename Allocator = std::allocator<std::pair<const K, V>>>
31a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughesclass SafeMap {
32a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes private:
330a9dc05e704bfd033bac2aa38a4fc6f6b8e6cf93Mathieu Chartier  typedef SafeMap<K, V, Comparator, Allocator> Self;
34a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
35a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes public:
3683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::key_compare key_compare;
37bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::value_compare value_compare;
3883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::allocator_type allocator_type;
3983cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::iterator iterator;
4083cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::const_iterator const_iterator;
4183cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::size_type size_type;
42bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::key_type key_type;
4383cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  typedef typename ::std::map<K, V, Comparator, Allocator>::value_type value_type;
4483cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko
4583cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  SafeMap() = default;
4683cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  explicit SafeMap(const key_compare& cmp, const allocator_type& allocator = allocator_type())
4783cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko    : map_(cmp, allocator) {
4883cc7ae96d4176533dd0391a1591d321b0a87f4fVladimir Marko  }
49a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
50748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  Self& operator=(const Self& rhs) {
51748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes    map_ = rhs.map_;
52748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes    return *this;
53748474146da0c6484fa3dca0a700f612d47550c3Elliott Hughes  }
54a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
55b19955d3c8fbd9588f7e17299e559d02938154b6Vladimir Marko  allocator_type get_allocator() const { return map_.get_allocator(); }
56bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  key_compare key_comp() const { return map_.key_comp(); }
57bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  value_compare value_comp() const { return map_.value_comp(); }
58bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko
59a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  iterator begin() { return map_.begin(); }
60a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  const_iterator begin() const { return map_.begin(); }
61a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  iterator end() { return map_.end(); }
62a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  const_iterator end() const { return map_.end(); }
63a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
64a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  bool empty() const { return map_.empty(); }
65a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_type size() const { return map_.size(); }
66a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
67bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  void swap(Self& other) { map_.swap(other.map_); }
6808f753d5859936f8d3524e9e4faa6cee353873eaIan Rogers  void clear() { map_.clear(); }
69bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  iterator erase(iterator it) { return map_.erase(it); }
70a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_type erase(const K& k) { return map_.erase(k); }
71a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
72a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  iterator find(const K& k) { return map_.find(k); }
73a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  const_iterator find(const K& k) const { return map_.find(k); }
74a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
752ac01fc279e8397beacf90302b0f215040eb78faVladimir Marko  iterator lower_bound(const K& k) { return map_.lower_bound(k); }
762ac01fc279e8397beacf90302b0f215040eb78faVladimir Marko  const_iterator lower_bound(const K& k) const { return map_.lower_bound(k); }
772ac01fc279e8397beacf90302b0f215040eb78faVladimir Marko
78a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_type count(const K& k) const { return map_.count(k); }
79a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
80a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  // Note that unlike std::map's operator[], this doesn't return a reference to the value.
81b2eb5c18d628dc84bdc424b5e5a491382d867e36TDYa  V Get(const K& k) const {
82b2eb5c18d628dc84bdc424b5e5a491382d867e36TDYa    const_iterator it = map_.find(k);
83a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    DCHECK(it != map_.end());
84a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    return it->second;
85a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  }
86a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
87a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  // Used to insert a new mapping.
88bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  iterator Put(const K& k, const V& v) {
89bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    std::pair<iterator, bool> result = map_.emplace(k, v);
907934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom    DCHECK(result.second);  // Check we didn't accidentally overwrite an existing value.
91bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    return result.first;
92bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  }
93bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko
94bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  // Used to insert a new mapping at a known position for better performance.
95bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko  iterator PutBefore(iterator pos, const K& k, const V& v) {
96bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    // Check that we're using the correct position and the key is not in the map.
97bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    DCHECK(pos == map_.end() || map_.key_comp()(k, pos->first));
98bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    DCHECK(pos == map_.begin() || map_.key_comp()((--iterator(pos))->first, k));
99bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko    return map_.emplace_hint(pos, k, v);
100a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  }
101a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
102a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  // Used to insert a new mapping or overwrite an existing mapping. Note that if the value type
103a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  // of this container is a pointer, any overwritten pointer will be lost and if this container
104a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  // was the owner, you have a leak.
105a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  void Overwrite(const K& k, const V& v) {
106d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee    std::pair<iterator, bool> result = map_.insert(std::make_pair(k, v));
107d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee    if (!result.second) {
108d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee      // Already there - update the value for the existing key
109d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee      result.first->second = v;
110d1643e41ef242ae656f667bf3c8b0324635cefd3buzbee    }
111a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  }
112a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
113a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  bool Equals(const Self& rhs) const {
114a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    return map_ == rhs.map_;
115a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  }
116a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
117a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes private:
1180a9dc05e704bfd033bac2aa38a4fc6f6b8e6cf93Mathieu Chartier  ::std::map<K, V, Comparator, Allocator> map_;
119a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes};
120a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
121bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Markotemplate <typename K, typename V, typename Comparator, typename Allocator>
122bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Markobool operator==(const SafeMap<K, V, Comparator, Allocator>& lhs,
123bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko                const SafeMap<K, V, Comparator, Allocator>& rhs) {
124a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  return lhs.Equals(rhs);
125a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes}
126a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
127bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Markotemplate <typename K, typename V, typename Comparator, typename Allocator>
128bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Markobool operator!=(const SafeMap<K, V, Comparator, Allocator>& lhs,
129bd72fc137a51257f61038ba21c15cf5f1abcdbefVladimir Marko                const SafeMap<K, V, Comparator, Allocator>& rhs) {
130a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  return !(lhs == rhs);
131a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes}
132a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
133a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes}  // namespace art
134a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
135fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif  // ART_RUNTIME_SAFE_MAP_H_
136