• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Copyright 2015 Google Inc.
2  //
3  // Licensed under the Apache License, Version 2.0 (the "License");
4  // you may not use this file except in compliance with the License.
5  // You may obtain a copy of the License at
6  //
7  //      http://www.apache.org/licenses/LICENSE-2.0
8  //
9  // Unless required by applicable law or agreed to in writing, software
10  // distributed under the License is distributed on an "AS IS" BASIS,
11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  // See the License for the specific language governing permissions and
13  // limitations under the License.
14  //
15  ////////////////////////////////////////////////////////////////////////////////
16  //
17  // The cache layer works as follows:
18  // The cache is implemented as a vector (of size 'cache_size') of shared
19  // pointers to pages recently used. The least recently used page is stored
20  // at the begining of the vector, the most recent at the end.
21  
22  #include "src/binary_parse/cached_paged_byte_array.h"
23  
24  #include <cstddef>
25  
26  namespace piex {
27  namespace binary_parse {
28  
CachedPagedByteArray(const PagedByteArray * paged_byte_array,size_t cache_size)29  CachedPagedByteArray::CachedPagedByteArray(
30      const PagedByteArray* paged_byte_array, size_t cache_size)
31      : paged_byte_array_(paged_byte_array), cache_size_(cache_size) {}
32  
getPage(size_t page_index,const unsigned char ** begin,const unsigned char ** end,PagedByteArray::PagePtr * page) const33  void CachedPagedByteArray::getPage(size_t page_index,
34                                     const unsigned char** begin,
35                                     const unsigned char** end,
36                                     PagedByteArray::PagePtr* page) const {
37    std::lock_guard<std::mutex> lock(mutex_);
38    size_t cache_index;
39    if (getFromCache(page_index, &cache_index)) {
40      // Cache hit, retrieve the page from the cache.
41      *begin = cached_pages_[cache_index].begin;
42      *end = cached_pages_[cache_index].end;
43      *page = cached_pages_[cache_index].page;
44  
45      // Remove the page to insert it at the end of the cache later.
46      cached_pages_.erase(cached_pages_.begin() +
47                          static_cast<std::ptrdiff_t>(cache_index));
48    } else {
49      // Cache miss, ask PagedByteArray to load the page.
50      paged_byte_array_->getPage(page_index, begin, end, page);
51  
52      // If the cache is full, remove the first (least recently used) page.
53      if (cached_pages_.size() >= cache_size_) {
54        cached_pages_.erase(cached_pages_.begin());
55      }
56    }
57  
58    // Cache the most recently used page to the end of the vector.
59    CachedPage cache_page;
60    cache_page.index = page_index;
61    cache_page.page = *page;
62    cache_page.begin = *begin;
63    cache_page.end = *end;
64    cached_pages_.push_back(cache_page);
65  }
66  
getFromCache(size_t page_index,size_t * cache_index) const67  bool CachedPagedByteArray::getFromCache(size_t page_index,
68                                          size_t* cache_index) const {
69    for (size_t i = 0; i < cached_pages_.size(); ++i) {
70      if (cached_pages_[i].index == page_index) {
71        *cache_index = i;
72        return true;
73      }
74    }
75    return false;
76  }
77  
78  }  // namespace binary_parse
79  }  // namespace piex
80