Codemod: use #include angle brackets in folly and thrift
[folly.git] / folly / experimental / symbolizer / ElfCache.cpp
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 #include <folly/experimental/symbolizer/ElfCache.h>
18
19 namespace folly { namespace symbolizer {
20
21 SignalSafeElfCache::SignalSafeElfCache(size_t capacity) {
22   map_.reserve(capacity);
23   slots_.reserve(capacity);
24
25   // Preallocate
26   for (size_t i = 0; i < capacity; ++i) {
27     slots_.push_back(std::make_shared<ElfFile>());
28   }
29 }
30
31 std::shared_ptr<ElfFile> SignalSafeElfCache::getFile(StringPiece p) {
32   if (p.size() > Path::kMaxSize) {
33     return nullptr;
34   }
35
36   Path path(p);
37   auto pos = map_.find(path);
38   if (pos != map_.end()) {
39     return slots_[pos->second];
40   }
41
42   size_t n = map_.size();
43   if (n >= slots_.size()) {
44     DCHECK_EQ(map_.size(), slots_.size());
45     return nullptr;
46   }
47
48   auto& f = slots_[n];
49   if (f->openNoThrow(path.data()) == -1) {
50     return nullptr;
51   }
52
53   map_[path] = n;
54   return f;
55 }
56
57 ElfCache::ElfCache(size_t capacity) : capacity_(capacity) { }
58
59 std::shared_ptr<ElfFile> ElfCache::getFile(StringPiece p) {
60   std::lock_guard<std::mutex> lock(mutex_);
61
62   auto pos = files_.find(p);
63   if (pos != files_.end()) {
64     // Found, move to back (MRU)
65     auto& entry = pos->second;
66     lruList_.erase(lruList_.iterator_to(*entry));
67     lruList_.push_back(*entry);
68     return filePtr(entry);
69   }
70
71   auto entry = std::make_shared<Entry>();
72   entry->path = p.str();
73   auto& path = entry->path;
74
75   // No negative caching
76   if (entry->file.openNoThrow(path.c_str()) == -1) {
77     return nullptr;
78   }
79
80   if (files_.size() == capacity_) {
81     auto& e = lruList_.front();
82     lruList_.pop_front();
83     files_.erase(e.path);
84   }
85
86   files_.emplace(entry->path, entry);
87   lruList_.push_back(*entry);
88
89   return filePtr(entry);
90 }
91
92 std::shared_ptr<ElfFile> ElfCache::filePtr(const std::shared_ptr<Entry>& e) {
93   // share ownership
94   return std::shared_ptr<ElfFile>(e, &e->file);
95 }
96
97 }}  // namespaces
98