generic_shared_internal.hpp
1 /*
2  * This file is part of CasADi.
3  *
4  * CasADi -- A symbolic framework for dynamic optimization.
5  * Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl,
6  * KU Leuven. All rights reserved.
7  * Copyright (C) 2011-2014 Greg Horn
8  *
9  * CasADi is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 3 of the License, or (at your option) any later version.
13  *
14  * CasADi is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with CasADi; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24 
25 
26 #ifndef CASADI_GENERIC_SHARED_INTERNAL_HPP
27 #define CASADI_GENERIC_SHARED_INTERNAL_HPP
28 
29 #include "generic_shared.hpp"
30 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
31 #include <memory>
32 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
33 
34 #ifdef CASADI_WITH_THREAD
35 #include <atomic>
36 #endif // CASADI_WITH_THREAD
37 
38 namespace casadi {
39 
42  template<typename Shared, typename Internal>
44  friend class GenericShared<Shared, Internal>;
45  public:
46 
49 
52 
55 
57  virtual ~GenericSharedInternal() = 0;
58 
60  casadi_int getCount() const;
61 
62  std::string debug_repr(const Internal*) const;
63 
68 
69  protected:
71  void initSingleton() {
72  casadi_assert_dev(static_cast<Internal*>(this)->count==0);
73  static_cast<Internal*>(this)->count++;
74  }
75 
78  static_cast<Internal*>(this)->count--;
79  }
80 
82  template<class B>
84  casadi_assert_dev(B::test_cast(static_cast<Internal*>(this)));
85  B ret;
86  ret.own(static_cast<Internal*>(this));
87  return ret;
88  }
89 
91  template<class B>
92  const B shared_from_this() const {
93  casadi_assert_dev(B::test_cast(static_cast<const Internal*>(this)));
94  B ret;
95  ret.own(const_cast<Internal*>(static_cast<const Internal*>(this)));
96  return ret;
97  }
98 
99  private:
102  };
103 
104  template<typename Shared, typename Internal>
105  class GenericWeakRefInternal : public Internal {
106  public:
107  // Constructor
108  GenericWeakRefInternal(Internal* raw);
109 
110  // Destructor
112 
113  // Raw pointer to the cached object
114  Internal* raw_;
115 
116 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
117  mutable std::shared_ptr<std::mutex> mutex_;
118 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
119  };
120 
121 
122  template<class A>
123  A getcopy(const A& a,
124  std::map<typename A::base_type*,
125  typename A::internal_base_type> & already_copied) {
126  A ret;
127  if (!a.is_null()) {
128  auto it =
129  already_copied.find(const_cast<typename A::base_type*>(a.get()));
130  if (it!=already_copied.end()) {
131  ret.own(it->second.get());
132  }
133  }
134  return ret;
135  }
136 
138 
139 
140  template<typename Shared, typename Internal>
143  static_cast<Internal*>(this)->count = 0; // reference counter is _not_ copied
144  weak_ref_ = nullptr; // nor will they have the same weak references
145  }
146 
147  template<typename Shared, typename Internal>
151  // do _not_ copy the reference counter
152  return *this;
153  }
154 
155  template<typename Shared, typename Internal>
157  static_cast<Internal*>(this)->count = 0;
158  weak_ref_ = nullptr;
159  }
160 
161  template<typename Shared, typename Internal>
162  std::string GenericSharedInternal<Shared, Internal>::debug_repr(const Internal* i) const {
163  // Note: i != this because of something something multiple inheritance
164  return str( (casadi_int)(i)) + "/" + static_cast<const Internal*>(this)->class_name();
165  }
166 
167  template<typename Shared, typename Internal>
169  #ifdef WITH_REFCOUNT_WARNINGS
170  if (static_cast<Internal*>(this)->count!=0) {
171  // Note that casadi_assert_warning cannot be used in destructors
172  std::cerr << "Reference counting failure." <<
173  "Possible cause: Circular dependency in user code." << std::endl;
174  }
175  #endif // WITH_REFCOUNT_WARNINGS
176  if (weak_ref_!=nullptr) {
177  // Assumption: no other GenericSharedInternal instances
178  // point to the same WeakRefInternal through weak_ref_
179  weak_ref_->kill();
180  delete weak_ref_;
181  weak_ref_ = nullptr;
182  }
183  }
184 
185  template<typename Shared, typename Internal>
187  return static_cast<const Internal*>(this)->count;
188  }
189 
190  template<typename Shared, typename Internal>
192  if (weak_ref_==nullptr) {
193  weak_ref_ = new GenericWeakRef<Shared, Internal>(static_cast<Internal*>(this));
194  }
195  return weak_ref_;
196  }
197 
198  template<typename Shared, typename Internal>
200  raw_(raw)
201 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
202  , mutex_(std::make_shared<std::mutex>())
203 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
204  {
205  }
206 
207  template<typename Shared, typename Internal>
209  }
210 
211 
212 } // namespace casadi
213 
214 
215 #endif // CASADI_GENERIC_SHARED_INTERNAL_HPP
const B shared_from_this() const
Get a shared object from the current internal object.
std::string debug_repr(const Internal *) const
casadi_int getCount() const
Get the reference count.
virtual ~GenericSharedInternal()=0
Destructor.
GenericSharedInternal(const GenericSharedInternal &node)
Copy constructor.
GenericSharedInternal & operator=(const GenericSharedInternal &node)
Assignment operator.
B shared_from_this()
Get a shared object from the current internal object.
GenericWeakRef< Shared, Internal > * weak()
Get a weak reference to the object.
The casadi namespace.
Definition: archiver.cpp:28
A getcopy(const A &a, std::map< typename A::base_type *, typename A::internal_base_type > &already_copied)
std::string str(const T &v)
String representation, any type.