26 #ifndef CASADI_GENERIC_SHARED_INTERNAL_HPP
27 #define CASADI_GENERIC_SHARED_INTERNAL_HPP
29 #include "generic_shared.hpp"
30 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
34 #ifdef CASADI_WITH_THREAD
42 template<
typename Shared,
typename Internal>
43 class GenericSharedInternal {
44 friend class GenericShared<Shared, Internal>;
48 GenericSharedInternal();
51 GenericSharedInternal(
const GenericSharedInternal& node);
54 GenericSharedInternal& operator=(
const GenericSharedInternal& node);
57 virtual ~GenericSharedInternal() = 0;
60 casadi_int getCount()
const;
62 std::string debug_repr(
const Internal*)
const;
67 GenericWeakRef<Shared, Internal>* weak();
71 void initSingleton() {
72 casadi_assert_dev(
static_cast<Internal*
>(
this)->count==0);
73 static_cast<Internal*
>(
this)->count++;
77 void destroySingleton() {
78 static_cast<Internal*
>(
this)->count--;
83 B shared_from_this() {
84 casadi_assert_dev(B::test_cast(
static_cast<Internal*
>(
this)));
86 ret.own(
static_cast<Internal*
>(
this));
92 const B shared_from_this()
const {
93 casadi_assert_dev(B::test_cast(
static_cast<const Internal*
>(
this)));
95 ret.own(
const_cast<Internal*
>(
static_cast<const Internal*
>(
this)));
101 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
103 std::atomic<GenericWeakRef<Shared, Internal>*> weak_ref_;
105 GenericWeakRef<Shared, Internal>* weak_ref_;
109 template<
typename Shared,
typename Internal>
110 class GenericWeakRefInternal :
public Internal {
113 GenericWeakRefInternal(Internal* raw);
116 ~GenericWeakRefInternal()
override;
119 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
121 std::atomic<Internal*> raw_;
126 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
127 mutable std::shared_ptr<std::mutex> mutex_;
133 A getcopy(
const A& a,
134 std::map<
typename A::base_type*,
135 typename A::internal_base_type> & already_copied) {
139 already_copied.find(
const_cast<typename A::base_type*
>(a.get()));
140 if (it!=already_copied.end()) {
141 ret.own(it->second.get());
150 template<
typename Shared,
typename Internal>
151 GenericSharedInternal<Shared, Internal>::
152 GenericSharedInternal(
const GenericSharedInternal& node) {
153 static_cast<Internal*
>(
this)->count = 0;
154 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
155 weak_ref_.store(
nullptr, std::memory_order_relaxed);
161 template<
typename Shared,
typename Internal>
162 GenericSharedInternal<Shared, Internal>&
163 GenericSharedInternal<Shared, Internal>::
164 operator=(
const GenericSharedInternal<Shared, Internal>& node) {
169 template<
typename Shared,
typename Internal>
170 GenericSharedInternal<Shared, Internal>::GenericSharedInternal() {
171 static_cast<Internal*
>(
this)->count = 0;
172 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
173 weak_ref_.store(
nullptr, std::memory_order_relaxed);
179 template<
typename Shared,
typename Internal>
180 std::string GenericSharedInternal<Shared, Internal>::debug_repr(
const Internal* i)
const {
182 return str( (casadi_int)(i)) +
"/" +
static_cast<const Internal*
>(
this)->class_name();
185 template<
typename Shared,
typename Internal>
186 GenericSharedInternal<Shared, Internal>::~GenericSharedInternal() {
187 #ifdef WITH_REFCOUNT_WARNINGS
188 if (
static_cast<Internal*
>(
this)->count!=0) {
190 std::cerr <<
"Reference counting failure." <<
191 "Possible cause: Circular dependency in user code." << std::endl;
194 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
195 GenericWeakRef<Shared, Internal>* weak_ref =
196 weak_ref_.exchange(
nullptr, std::memory_order_acq_rel);
198 GenericWeakRef<Shared, Internal>* weak_ref = weak_ref_;
201 if (weak_ref !=
nullptr) {
209 template<
typename Shared,
typename Internal>
210 casadi_int GenericSharedInternal<Shared, Internal>::getCount()
const {
211 return static_cast<const Internal*
>(
this)->count;
214 template<
typename Shared,
typename Internal>
215 GenericWeakRef<Shared, Internal>* GenericSharedInternal<Shared, Internal>::weak() {
216 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
217 auto* w = weak_ref_.load(std::memory_order_acquire);
219 auto* nw =
new GenericWeakRef<Shared, Internal>(
static_cast<Internal*
>(
this));
220 GenericWeakRef<Shared, Internal>* expected =
nullptr;
221 if (weak_ref_.compare_exchange_strong(
222 expected, nw, std::memory_order_release, std::memory_order_acquire)) {
231 if (weak_ref_==
nullptr) {
232 weak_ref_ =
new GenericWeakRef<Shared, Internal>(
static_cast<Internal*
>(
this));
238 template<
typename Shared,
typename Internal>
239 GenericWeakRefInternal<Shared, Internal>::GenericWeakRefInternal(Internal* raw) :
241 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
242 , mutex_(std::make_shared<std::mutex>())
247 template<
typename Shared,
typename Internal>
248 GenericWeakRefInternal<Shared, Internal>::~GenericWeakRefInternal() {