26 #ifndef CASADI_GENERIC_SHARED_HPP
27 #define CASADI_GENERIC_SHARED_HPP
29 #include "casadi_common.hpp"
30 #include "exception.hpp"
31 #include <unordered_map>
34 #ifdef CASADI_WITH_THREAD
35 #ifdef CASADI_WITH_THREAD_MINGW
36 #include <mingw.mutex.h>
47 template<
typename Shared,
typename Internal>
52 template<
typename Shared,
typename Internal>
53 class GenericSharedInternal;
55 template<
typename Shared,
typename Internal>
56 class GenericWeakRefInternal;
59 template<
typename Shared,
typename Internal>
62 template<
class B,
class S>
friend B shared_cast(S& A);
63 template<
class B,
class S>
friend const B shared_cast(
const S& A);
89 void own(Internal* node);
96 void assign(Internal* node);
99 Internal* get()
const;
102 casadi_int getCount()
const;
108 Internal* operator->()
const;
112 std::string debug_repr()
const;
116 bool is_null()
const;
123 casadi_int __hash__()
const;
140 template<
typename Shared,
typename Internal>
143 friend class GenericSharedInternal<Shared, Internal>;
160 Shared shared()
const;
170 bool shared_if_alive(Shared& shared)
const;
175 GenericWeakRefInternal<Shared, Internal>* operator->();
180 const GenericWeakRefInternal<Shared, Internal>* operator->()
const;
182 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
183 std::shared_ptr<std::mutex> get_mutex()
const;
207 template<
class B,
class S>
208 B shared_cast(S& A) {
211 typename S::internal_base_type* ptr = A.get();
217 if (!B::test_cast(ptr))
return ret;
229 template<
class B,
class S>
230 const B shared_cast(
const S& A) {
232 return shared_cast<B, S>(A_copy);
241 template<
typename K,
typename T>
244 void tocache(
const K& key,
const T& f,
bool needs_lock=
true,
246 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
248 casadi::conditional_lock_guard<std::mutex> lock(mtx_, needs_lock);
251 auto it = cache_.find(key);
253 if (it == cache_.end()) {
254 cache_.emplace(key, f);
255 }
else if (!it->second.alive()) {
261 for (
auto it = cache_.begin(); it!=cache_.end(); ++it) {
262 if (!it->second.alive()) {
277 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
279 std::lock_guard<std::mutex> lock(mtx_);
281 if (!incache(key, f,
false)) {
282 tocache(key, f,
false, prune);
285 bool incache(
const K& key, T& f,
bool needs_lock=
true)
const {
286 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
288 casadi::conditional_lock_guard<std::mutex> lock(mtx_, needs_lock);
290 auto it = cache_.find(key);
291 typename T::base_type temp;
292 if (it!=cache_.end() && it->second.shared_if_alive(temp)) {
293 f = shared_cast<T>(temp);
301 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
303 std::lock_guard<std::mutex> lock(mtx_);
305 for (
auto it = cache_.begin(); it!=cache_.end();) {
306 if (!it->second.alive()) {
307 it = cache_.erase(it);
313 void cache(std::vector<K>& keys, std::vector<T>& entries)
const {
314 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
316 std::lock_guard<std::mutex> lock(mtx_);
321 for (
auto&& cf : cache_) {
322 typename T::base_type temp;
323 if (cf.second.shared_if_alive(temp)) {
324 keys.push_back(cf.first);
325 entries.push_back(shared_cast<T>(temp));
330 std::unordered_map<K,
333 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
334 mutable std::mutex mtx_;
342 template<
typename K,
typename T>
345 void tocache(
const K& key,
const T& f,
bool needs_lock=
true,
347 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
349 casadi::conditional_lock_guard<std::mutex> lock(mtx_, needs_lock);
352 const void* k = key.get();
353 auto it = pre_cache_.find(k);
355 if (it == pre_cache_.end()) {
356 pre_cache_.emplace(k, key);
357 cache_.emplace(k, f);
358 }
else if (it->second.get() !=
typename K::base_type(key).weak()->get()) {
362 cache_.find(k)->second = f;
367 for (
auto it = pre_cache_.begin(); it!=pre_cache_.end(); ++it) {
368 if (!it->second.alive()) {
369 const void* dead = it->first;
370 pre_cache_.erase(it);
385 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
387 std::lock_guard<std::mutex> lock(mtx_);
389 if (!incache(key, f,
false)) {
390 tocache(key, f,
false, prune);
393 bool incache(
const K& key, T& f,
bool needs_lock=
true)
const {
394 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
396 casadi::conditional_lock_guard<std::mutex> lock(mtx_, needs_lock);
398 const void* k = key.get();
399 auto it = pre_cache_.find(k);
401 if (it!=pre_cache_.end() && it->second.shared_if_alive(temp)) {
402 auto it2 = cache_.find(k);
410 std::unordered_map<
const void*,
413 std::unordered_map<const void*, T> cache_;
414 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
415 mutable std::mutex mtx_;
423 template<
typename K,
typename T>
431 auto it = cache_.find(key);
432 if (it != cache_.end()) {
444 std::unordered_map<K, T> cache_;
void tocache_if_missing(const K &key, T &f, bool prune=true)
void tocache(const K &key, const T &f, bool needs_lock=true, bool prune=true)
bool incache(const K &key, T &f, bool needs_lock=true) const
void tocache(const K &key, const T &value)
const std::unordered_map< K, T > & cache_map() const
bool incache(const K &key, T &value) const
bool incache(const K &key, T &f, bool needs_lock=true) const
void cache(std::vector< K > &keys, std::vector< T > &entries) const
void tocache_if_missing(const K &key, T &f, bool prune=true)
void tocache(const K &key, const T &f, bool needs_lock=true, bool prune=true)