1 //===-- ThreadSafeSTLMap.h --------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef liblldb_ThreadSafeSTLMap_h_
11 #define liblldb_ThreadSafeSTLMap_h_
12 
13 // C Includes
14 // C++ Includes
15 #include <map>
16 
17 // Other libraries and framework includes
18 // Project includes
19 #include "lldb/Host/Mutex.h"
20 
21 namespace lldb_private {
22 
23 template <typename _Key, typename _Tp>
24 class ThreadSafeSTLMap
25 {
26 public:
27     typedef std::map<_Key,_Tp> collection;
28     typedef typename collection::iterator iterator;
29     typedef typename collection::const_iterator const_iterator;
30     //------------------------------------------------------------------
31     // Constructors and Destructors
32     //------------------------------------------------------------------
ThreadSafeSTLMap()33     ThreadSafeSTLMap() :
34         m_collection (),
35         m_mutex (Mutex::eMutexTypeRecursive)
36     {
37     }
38 
~ThreadSafeSTLMap()39     ~ThreadSafeSTLMap()
40     {
41     }
42 
43     bool
IsEmpty()44     IsEmpty() const
45     {
46         Mutex::Locker locker(m_mutex);
47         return m_collection.empty();
48     }
49 
50     void
Clear()51     Clear()
52     {
53         Mutex::Locker locker(m_mutex);
54         return m_collection.clear();
55     }
56 
57     size_t
Erase(const _Key & key)58     Erase (const _Key& key)
59     {
60         Mutex::Locker locker(m_mutex);
61         return EraseNoLock (key);
62     }
63 
64     size_t
EraseNoLock(const _Key & key)65     EraseNoLock (const _Key& key)
66     {
67         return m_collection.erase (key);
68     }
69 
70     bool
GetValueForKey(const _Key & key,_Tp & value)71     GetValueForKey (const _Key& key, _Tp &value) const
72     {
73         Mutex::Locker locker(m_mutex);
74         return GetValueForKeyNoLock (key, value);
75     }
76 
77     // Call this if you have already manually locked the mutex using the
78     // GetMutex() accessor
79     bool
GetValueForKeyNoLock(const _Key & key,_Tp & value)80     GetValueForKeyNoLock (const _Key& key, _Tp &value) const
81     {
82         const_iterator pos = m_collection.find(key);
83         if (pos != m_collection.end())
84         {
85             value = pos->second;
86             return true;
87         }
88         return false;
89     }
90 
91     bool
GetFirstKeyForValue(const _Tp & value,_Key & key)92     GetFirstKeyForValue (const _Tp &value, _Key& key) const
93     {
94         Mutex::Locker locker(m_mutex);
95         return GetFirstKeyForValueNoLock (value, key);
96     }
97 
98     bool
GetFirstKeyForValueNoLock(const _Tp & value,_Key & key)99     GetFirstKeyForValueNoLock (const _Tp &value, _Key& key) const
100     {
101         const_iterator pos, end = m_collection.end();
102         for (pos = m_collection.begin(); pos != end; ++pos)
103         {
104             if (pos->second == value)
105             {
106                 key = pos->first;
107                 return true;
108             }
109         }
110         return false;
111     }
112 
113     bool
LowerBound(const _Key & key,_Key & match_key,_Tp & match_value,bool decrement_if_not_equal)114     LowerBound (const _Key& key,
115                 _Key& match_key,
116                 _Tp &match_value,
117                 bool decrement_if_not_equal) const
118     {
119         Mutex::Locker locker(m_mutex);
120         return LowerBoundNoLock (key, match_key, match_value, decrement_if_not_equal);
121     }
122 
123     bool
LowerBoundNoLock(const _Key & key,_Key & match_key,_Tp & match_value,bool decrement_if_not_equal)124     LowerBoundNoLock (const _Key& key,
125                       _Key& match_key,
126                       _Tp &match_value,
127                       bool decrement_if_not_equal) const
128     {
129         const_iterator pos = m_collection.lower_bound (key);
130         if (pos != m_collection.end())
131         {
132             match_key = pos->first;
133             if (decrement_if_not_equal && key != match_key && pos != m_collection.begin())
134             {
135                 --pos;
136                 match_key = pos->first;
137             }
138             match_value = pos->second;
139             return true;
140         }
141         return false;
142     }
143 
144     iterator
lower_bound_unsafe(const _Key & key)145     lower_bound_unsafe (const _Key& key)
146     {
147         return m_collection.lower_bound (key);
148     }
149 
150     void
SetValueForKey(const _Key & key,const _Tp & value)151     SetValueForKey (const _Key& key, const _Tp &value)
152     {
153         Mutex::Locker locker(m_mutex);
154         SetValueForKeyNoLock (key, value);
155     }
156 
157     // Call this if you have already manually locked the mutex using the
158     // GetMutex() accessor
159     void
SetValueForKeyNoLock(const _Key & key,const _Tp & value)160     SetValueForKeyNoLock (const _Key& key, const _Tp &value)
161     {
162         m_collection[key] = value;
163     }
164 
165     Mutex &
GetMutex()166     GetMutex ()
167     {
168         return m_mutex;
169     }
170 
171 private:
172     collection m_collection;
173     mutable Mutex m_mutex;
174 
175     //------------------------------------------------------------------
176     // For ThreadSafeSTLMap only
177     //------------------------------------------------------------------
178     DISALLOW_COPY_AND_ASSIGN (ThreadSafeSTLMap);
179 };
180 
181 
182 } // namespace lldb_private
183 
184 #endif  // liblldb_ThreadSafeSTLMap_h_
185