Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / experimental / symbolizer / ElfCache.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef FOLLY_SYMBOLIZER_ELFCACHE_H_
18 #define FOLLY_SYMBOLIZER_ELFCACHE_H_
19
20 #include <cstring>
21 #include <limits.h>  // for PATH_MAX
22 #include <memory>
23 #include <mutex>
24 #include <string>
25 #include <vector>
26 #include <unordered_map>
27
28 #include <boost/operators.hpp>
29 #include <boost/container/flat_map.hpp>
30 #include <boost/intrusive/list.hpp>
31 #include <glog/logging.h>
32
33 #include <folly/experimental/symbolizer/Elf.h>
34
35 namespace folly { namespace symbolizer {
36
37 class ElfCacheBase {
38  public:
39   virtual std::shared_ptr<ElfFile> getFile(StringPiece path) = 0;
40   virtual ~ElfCacheBase() { }
41 };
42
43 /**
44  * Cache ELF files. Async-signal-safe: does memory allocation upfront.
45  *
46  * Will not grow; once the capacity is reached, lookups for files that
47  * aren't already in the cache will fail (return nullptr).
48  *
49  * Not MT-safe. May not be used concurrently from multiple threads.
50  *
51  * NOTE that async-signal-safety is preserved only as long as the
52  * SignalSafeElfCache object exists; after the SignalSafeElfCache object
53  * is destroyed, destroying returned shared_ptr<ElfFile> objects may
54  * cause ElfFile objects to be destroyed, and that's not async-signal-safe.
55  */
56 class SignalSafeElfCache : public ElfCacheBase {
57  public:
58   explicit SignalSafeElfCache(size_t capacity);
59
60   std::shared_ptr<ElfFile> getFile(StringPiece path) override;
61
62  private:
63   // We can't use std::string (allocating memory is bad!) so we roll our
64   // own wrapper around a fixed-size, null-terminated string.
65   class Path : private boost::totally_ordered<Path> {
66    public:
67     explicit Path(StringPiece s) {
68       DCHECK_LE(s.size(), kMaxSize);
69       memcpy(data_, s.data(), s.size());
70       data_[s.size()] = '\0';
71     }
72
73     bool operator<(const Path& other) const {
74       return strcmp(data_, other.data_) < 0;
75     }
76
77     bool operator==(const Path& other) const {
78       return strcmp(data_, other.data_) == 0;
79     }
80
81     const char* data() const {
82       return data_;
83     }
84
85     static constexpr size_t kMaxSize = PATH_MAX - 1;
86
87    private:
88     char data_[kMaxSize + 1];
89   };
90
91   boost::container::flat_map<Path, int> map_;
92   std::vector<std::shared_ptr<ElfFile>> slots_;
93 };
94
95 /**
96  * General-purpose ELF file cache.
97  *
98  * LRU of given capacity. MT-safe (uses locking). Not async-signal-safe.
99  */
100 class ElfCache : public ElfCacheBase {
101  public:
102   explicit ElfCache(size_t capacity);
103
104   std::shared_ptr<ElfFile> getFile(StringPiece path) override;
105
106  private:
107   std::mutex mutex_;
108
109   typedef boost::intrusive::list_member_hook<> LruLink;
110
111   struct Entry {
112     std::string path;
113     ElfFile file;
114     LruLink lruLink;
115   };
116
117   static std::shared_ptr<ElfFile> filePtr(const std::shared_ptr<Entry>& e);
118
119   size_t capacity_;
120   std::unordered_map<
121     StringPiece,
122     std::shared_ptr<Entry>,
123     StringPieceHash> files_;
124
125   typedef boost::intrusive::list<
126       Entry,
127       boost::intrusive::member_hook<Entry, LruLink, &Entry::lruLink>,
128       boost::intrusive::constant_time_size<false>> LruList;
129   LruList lruList_;
130 };
131
132 }}  // namespaces
133
134 #endif /* FOLLY_SYMBOLIZER_ELFCACHE_H_ */
135