aboutsummaryrefslogtreecommitdiff
path: root/src/binary_parse/cached_paged_byte_array.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/binary_parse/cached_paged_byte_array.cc')
-rwxr-xr-xsrc/binary_parse/cached_paged_byte_array.cc79
1 files changed, 79 insertions, 0 deletions
diff --git a/src/binary_parse/cached_paged_byte_array.cc b/src/binary_parse/cached_paged_byte_array.cc
new file mode 100755
index 0000000..83b6c03
--- /dev/null
+++ b/src/binary_parse/cached_paged_byte_array.cc
@@ -0,0 +1,79 @@
+// Copyright 2015 Google Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+////////////////////////////////////////////////////////////////////////////////
+//
+// The cache layer works as follows:
+// The cache is implemented as a vector (of size 'cache_size') of shared
+// pointers to pages recently used. The least recently used page is stored
+// at the begining of the vector, the most recent at the end.
+
+#include "src/binary_parse/cached_paged_byte_array.h"
+
+#include <cstddef>
+
+namespace piex {
+namespace binary_parse {
+
+CachedPagedByteArray::CachedPagedByteArray(
+ const PagedByteArray* paged_byte_array, size_t cache_size)
+ : paged_byte_array_(paged_byte_array), cache_size_(cache_size) {}
+
+void CachedPagedByteArray::getPage(size_t page_index,
+ const unsigned char** begin,
+ const unsigned char** end,
+ PagedByteArray::PagePtr* page) const {
+ std::lock_guard<std::mutex> lock(mutex_);
+ size_t cache_index;
+ if (getFromCache(page_index, &cache_index)) {
+ // Cache hit, retrieve the page from the cache.
+ *begin = cached_pages_[cache_index].begin;
+ *end = cached_pages_[cache_index].end;
+ *page = cached_pages_[cache_index].page;
+
+ // Remove the page to insert it at the end of the cache later.
+ cached_pages_.erase(cached_pages_.begin() +
+ static_cast<std::ptrdiff_t>(cache_index));
+ } else {
+ // Cache miss, ask PagedByteArray to load the page.
+ paged_byte_array_->getPage(page_index, begin, end, page);
+
+ // If the cache is full, remove the first (least recently used) page.
+ if (cached_pages_.size() >= cache_size_) {
+ cached_pages_.erase(cached_pages_.begin());
+ }
+ }
+
+ // Cache the most recently used page to the end of the vector.
+ CachedPage cache_page;
+ cache_page.index = page_index;
+ cache_page.page = *page;
+ cache_page.begin = *begin;
+ cache_page.end = *end;
+ cached_pages_.push_back(cache_page);
+}
+
+bool CachedPagedByteArray::getFromCache(size_t page_index,
+ size_t* cache_index) const {
+ for (size_t i = 0; i < cached_pages_.size(); ++i) {
+ if (cached_pages_[i].index == page_index) {
+ *cache_index = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace binary_parse
+} // namespace piex