1
2 // =================================================================================================
3 // This file is part of the CLBlast project. The project is licensed under Apache Version 2.0. This
4 // project loosely follows the Google C++ styleguide and uses a tab-size of two spaces and a max-
5 // width of 100 characters per line.
6 //
7 // Author(s):
8 // Cedric Nugteren <www.cedricnugteren.nl>
9 //
10 // This file implements the caching functionality of compiled binaries and programs.
11 //
12 // =================================================================================================
13
14 #include <string>
15 #include <vector>
16 #include <mutex>
17
18 #include "database/database.hpp"
19 #include "cache.hpp"
20
21 namespace clblast {
22 // =================================================================================================
23
24 template <typename Key, typename Value>
25 template <typename U>
Get(const U & key,bool * in_cache) const26 Value Cache<Key, Value>::Get(const U &key, bool *in_cache) const {
27 std::lock_guard<std::mutex> lock(cache_mutex_);
28
29 #if __cplusplus >= 201402L
30 // generalized std::map::find() of C++14
31 auto it = cache_.find(key);
32 #else
33 // O(n) lookup in a vector
34 auto it = std::find_if(cache_.begin(), cache_.end(), [&] (const std::pair<Key, Value> &pair) {
35 return pair.first == key;
36 });
37 #endif
38 if (it == cache_.end()) {
39 if (in_cache) {
40 *in_cache = false;
41 }
42 return Value();
43 }
44
45 if (in_cache) {
46 *in_cache = true;
47 }
48 return it->second;
49 }
50
51 template <typename Key, typename Value>
Store(Key && key,Value && value)52 void Cache<Key, Value>::Store(Key &&key, Value &&value) {
53 std::lock_guard<std::mutex> lock(cache_mutex_);
54
55 #if __cplusplus >= 201402L
56 // emplace() into a map
57 auto r = cache_.emplace(std::move(key), std::move(value));
58 if (!r.second) {
59 throw LogicError("Cache::Store: object already in cache");
60 }
61 #else
62 // emplace_back() into a vector
63 cache_.emplace_back(std::move(key), std::move(value));
64 #endif
65 }
66
67 template <typename Key, typename Value>
Remove(const Key & key)68 void Cache<Key, Value>::Remove(const Key &key) {
69 std::lock_guard<std::mutex> lock(cache_mutex_);
70 #if __cplusplus >= 201402L
71 cache_.erase(key);
72 #else
73 auto it = cache_.begin();
74 while (it != cache_.end()) {
75 if ((*it).first == key) {
76 it = cache_.erase(it);
77 }
78 else ++it;
79 }
80 #endif
81 }
82
83 template <typename Key, typename Value>
84 template <int I1, int I2>
RemoveBySubset(const Key & key)85 void Cache<Key, Value>::RemoveBySubset(const Key &key) {
86 std::lock_guard<std::mutex> lock(cache_mutex_);
87 auto it = cache_.begin();
88 while (it != cache_.end()) {
89 const auto current_key = (*it).first;
90 if ((std::get<I1>(key) == std::get<I1>(current_key)) &&
91 (std::get<I2>(key) == std::get<I2>(current_key))) {
92 it = cache_.erase(it);
93 }
94 else ++it;
95 }
96 }
97
98 template <typename Key, typename Value>
Invalidate()99 void Cache<Key, Value>::Invalidate() {
100 std::lock_guard<std::mutex> lock(cache_mutex_);
101
102 cache_.clear();
103 }
104
105 template <typename Key, typename Value>
Instance()106 Cache<Key, Value> &Cache<Key, Value>::Instance() {
107 return instance_;
108 }
109
110 template <typename Key, typename Value>
111 Cache<Key, Value> Cache<Key, Value>::instance_;
112
113 // =================================================================================================
114
115 template class Cache<BinaryKey, std::string>;
116 template std::string BinaryCache::Get(const BinaryKeyRef &, bool *) const;
117
118 // =================================================================================================
119
120 template class Cache<ProgramKey, Program>;
121 template Program ProgramCache::Get(const ProgramKeyRef &, bool *) const;
122 template void ProgramCache::RemoveBySubset<1, 2>(const ProgramKey &); // precision and routine name
123
124 // =================================================================================================
125
126 template class Cache<DatabaseKey, Database>;
127 template Database DatabaseCache::Get(const DatabaseKeyRef &, bool *) const;
128
129 // =================================================================================================
130 } // namespace clblast
131