tesseract v5.3.3.20231005
object_cache.h
Go to the documentation of this file.
1
2// File: object_cache.h
3// Description: A string indexed object cache.
4// Author: David Eger
5//
6// (C) Copyright 2012, Google Inc.
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License at
10// http://www.apache.org/licenses/LICENSE-2.0
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16//
18
19#ifndef TESSERACT_CCUTIL_OBJECT_CACHE_H_
20#define TESSERACT_CCUTIL_OBJECT_CACHE_H_
21
22#include <functional> // for std::function
23#include <mutex> // for std::mutex
24#include <string>
25#include <vector> // for std::vector
26#include "ccutil.h"
27#include "errcode.h"
28
29namespace tesseract {
30
31// A simple object cache which maps a string to an object of type T.
32// Usually, these are expensive objects that are loaded from disk.
33// Reference counting is performed, so every Get() needs to be followed later
34// by a Free(). Actual deletion is accomplished by DeleteUnusedObjects().
35template <typename T>
37public:
38 ObjectCache() = default;
40 std::lock_guard<std::mutex> guard(mu_);
41 for (auto &it : cache_) {
42 if (it.count > 0) {
43 tprintf(
44 "ObjectCache(%p)::~ObjectCache(): WARNING! LEAK! object %p "
45 "still has count %d (id %s)\n",
46 static_cast<void *>(this), static_cast<void *>(it.object),
47 it.count, it.id.c_str());
48 } else {
49 delete it.object;
50 it.object = nullptr;
51 }
52 }
53 }
54
55 // Return a pointer to the object identified by id.
56 // If we haven't yet loaded the object, use loader to load it.
57 // If loader fails to load it, record a nullptr entry in the cache
58 // and return nullptr -- further attempts to load will fail (even
59 // with a different loader) until DeleteUnusedObjects() is called.
60 // We delete the given loader.
61 T *Get(const std::string &id, std::function<T *()> loader) {
62 T *retval = nullptr;
63 std::lock_guard<std::mutex> guard(mu_);
64 for (auto &it : cache_) {
65 if (id == it.id) {
66 retval = it.object;
67 if (it.object != nullptr) {
68 it.count++;
69 }
70 return retval;
71 }
72 }
73 cache_.push_back(ReferenceCount());
74 ReferenceCount &rc = cache_.back();
75 rc.id = id;
76 retval = rc.object = loader();
77 rc.count = (retval != nullptr) ? 1 : 0;
78 return retval;
79 }
80
81 // Decrement the count for t.
82 // Return whether we knew about the given pointer.
83 bool Free(T *t) {
84 if (t == nullptr) {
85 return false;
86 }
87 std::lock_guard<std::mutex> guard(mu_);
88 for (auto &it : cache_) {
89 if (it.object == t) {
90 --it.count;
91 return true;
92 }
93 }
94 return false;
95 }
96
98 std::lock_guard<std::mutex> guard(mu_);
99 cache_.erase(std::remove_if(cache_.begin(), cache_.end(),
100 [](const ReferenceCount &it) {
101 if (it.count <= 0) {
102 delete it.object;
103 return true;
104 } else {
105 return false;
106 }
107 }),
108 cache_.end());
109 }
110
111private:
112 struct ReferenceCount {
113 std::string id; // A unique ID to identify the object (think path on disk)
114 T *object; // A copy of the object in memory. Can be delete'd.
115 int count; // A count of the number of active users of this object.
116 };
117
118 std::mutex mu_;
119 std::vector<ReferenceCount> cache_;
120};
121
122} // namespace tesseract
123
124#endif // TESSERACT_CCUTIL_OBJECT_CACHE_H_
int * count
void tprintf(const char *format,...)
Definition: tprintf.cpp:41
T * Get(const std::string &id, std::function< T *()> loader)
Definition: object_cache.h:61