SourceXtractorPlusPlus 0.18
SourceXtractor++, the next generation SExtractor
TileManager.cpp
Go to the documentation of this file.
1
17/*
18 * TileManager.cpp
19 *
20 * Created on: Feb 23, 2018
21 * Author: mschefer
22 */
23
25
26namespace SourceXtractor {
27
30
31bool TileKey::operator==(const TileKey& other) const {
32 return m_source == other.m_source && m_tile_x == other.m_tile_x && m_tile_y == other.m_tile_y;
33}
34
37 str << m_source.get() << "[" << m_source->getRepr() << "] " << m_tile_x << "," << m_tile_y;
38 return str.str();
39}
40
41
42TileManager::TileManager() : m_tile_width(256), m_tile_height(256),
43 m_max_memory(100 * 1024L * 1024L), m_total_memory_used(0) {
44}
45
48}
49
50void TileManager::setOptions(int tile_width, int tile_height, int max_memory) {
51 flush();
52
53 boost::lock_guard<boost::shared_mutex> wr_lock(m_mutex);
54 m_tile_width = tile_width;
55 m_tile_height = tile_height;
56 m_max_memory = max_memory * 1024L * 1024L;
57}
58
60 // empty anything still stored in cache
62
63 boost::lock_guard<boost::shared_mutex> wr_lock(m_mutex);
64 m_tile_list.clear();
65 m_tile_map.clear();
67}
68
69/*
70 * boost::upgrade_lock can only be acquired by a single thread, even if none of them
71 * ends needing an exclusive lock. Cache lookup must be done with a shared_lock instead
72 * so multiples can retrieve from the cache at the same time.
73 */
75 boost::shared_lock<boost::shared_mutex> shared_rd_lock(m_mutex);
76
77 auto it = m_tile_map.find(key);
78 if (it != m_tile_map.end()) {
79#ifndef NDEBUG
80 s_tile_logger.debug() << "Cache hit " << key;
81#endif
82 return std::dynamic_pointer_cast<ImageTile>(it->second);
83 }
84 return nullptr;
85}
86
87/*
88 * If the mutex does not exist, we need an upgradable lock
89 */
91 boost::upgrade_lock<boost::shared_mutex> upgrade_lock(m_mutex);
92 auto mit = m_mutex_map.find(src_ptr);
93 if (mit == m_mutex_map.end()) {
94 boost::upgrade_to_unique_lock<boost::shared_mutex> unique_lock(upgrade_lock);
95 mit = m_mutex_map.emplace(src_ptr, std::make_shared<boost::mutex>()).first;
96 }
97 return mit->second;
98}
99
104 TileKey key{std::static_pointer_cast<const ImageSource>(source), x, y};
105
106 // Try from the cache, this can be done by multiple threads in parallel
107 auto tile = tryTileFromCache(key);
108 if (tile) {
109 return tile;
110 }
111
112 // Cache miss, we need to ask the underlying source.
113 // First, we need a mutex only for that source, and that needs writing to the tile manager.
114 auto img_mutex = getMutexForImageSource(source.get());
115
116 // Here we block access only to this specific image source
117 boost::lock_guard<boost::mutex> img_lock(*img_mutex);
118
119 // Try again from the cache, maybe someone put it there while we waited for the image lock
120 tile = tryTileFromCache(key);
121 if (tile) {
122 return tile;
123 }
124
125 tile = source->getImageTile(x, y,
126 std::min(m_tile_width, source->getWidth() - x),
127 std::min(m_tile_height, source->getHeight() - y));
128
129 // Here we need to acquire the mutex in write mode!
130 boost::lock_guard<boost::shared_mutex> wr_lock(m_mutex);
131 addTile(key, std::static_pointer_cast<ImageTile>(tile));
133 return tile;
134}
135
137 if (s_instance == nullptr) {
138 s_instance = std::make_shared<TileManager>();
139 }
140 return s_instance;
141}
142
144 boost::lock_guard<boost::shared_mutex> wr_lock(m_mutex);
145
146 for (auto tile_key : m_tile_list) {
147 m_tile_map.at(tile_key)->saveIfModified();
148 }
149}
150
152 return m_tile_width;
153}
154
156 return m_tile_height;
157}
158
160#ifndef NDEBUG
161 s_tile_logger.debug() << "Cache eviction " << tile_key;
162#endif
163
164 auto& tile = m_tile_map.at(tile_key);
165
166 tile->saveIfModified();
167 m_total_memory_used -= tile->getTileMemorySize();
168
169 m_tile_map.erase(tile_key);
170}
171
174 assert(m_tile_list.size() > 0);
175 auto tile_to_remove = m_tile_list.back();
176 removeTile(tile_to_remove);
177 m_tile_list.pop_back();
178 }
179}
180
182#ifndef NDEBUG
183 s_tile_logger.debug() << "Cache miss " << key;
184#endif
185
186 m_tile_map[key] = tile;
187 m_tile_list.push_front(key);
188 m_total_memory_used += tile->getTileMemorySize();
189}
190
191}
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > x
std::shared_ptr< DependentParameter< std::shared_ptr< EngineParameter > > > y
void debug(const std::string &logMessage)
static Logging getLogger(const std::string &name="")
std::unordered_map< const ImageSource *, std::shared_ptr< boost::mutex > > m_mutex_map
Definition: TileManager.h:115
std::shared_ptr< ImageTile > getTileForPixel(int x, int y, std::shared_ptr< const ImageSource > source)
boost::shared_mutex m_mutex
Definition: TileManager.h:118
std::list< TileKey > m_tile_list
Definition: TileManager.h:116
std::shared_ptr< ImageTile > tryTileFromCache(const TileKey &key)
Definition: TileManager.cpp:74
void removeTile(TileKey tile_key)
void addTile(TileKey key, std::shared_ptr< ImageTile > tile)
void setOptions(int tile_width, int tile_height, int max_memory)
Definition: TileManager.cpp:50
static std::shared_ptr< TileManager > getInstance()
std::unordered_map< TileKey, std::shared_ptr< ImageTile > > m_tile_map
Definition: TileManager.h:114
std::shared_ptr< boost::mutex > & getMutexForImageSource(const ImageSource *)
Definition: TileManager.cpp:90
T get(T... args)
T min(T... args)
static Elements::Logging s_tile_logger
Definition: TileManager.cpp:29
static std::shared_ptr< TileManager > s_instance
Definition: TileManager.cpp:28
T str(T... args)
bool operator==(const TileKey &other) const
Definition: TileManager.cpp:31
std::shared_ptr< const ImageSource > m_source
Definition: TileManager.h:43
std::string getRepr() const
Definition: TileManager.cpp:35