generic_shared_impl.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_IMPL_HPP
27 #define CASADI_GENERIC_SHARED_IMPL_HPP
28 
29 #ifdef WITH_EXTRA_CHECKS
30 #include "function.hpp"
31 #endif // WITH_EXTRA_CHECKS
32 
33 namespace casadi {
34 
35  template<typename Shared, typename Internal>
36  void GenericShared<Shared, Internal>::count_up() {
37 #ifdef WITH_EXTRA_CHECKS
38  casadi_assert_dev(Function::call_depth_==0);
39 #endif // WITH_EXTRA_CHECKS
40 
41  if (node) static_cast<Internal*>(node)->count++;
42 
43  }
44 
45  template<typename Shared, typename Internal>
46  void GenericShared<Shared, Internal>::count_down() {
47 #ifdef WITH_EXTRA_CHECKS
48  casadi_assert_dev(Function::call_depth_==0);
49 #endif // WITH_EXTRA_CHECKS
50  if (!node) return;
51 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
52  GenericWeakRef<Shared, Internal>* weak_ref =
53  node->weak_ref_.load(std::memory_order_acquire);
54 #else
55  GenericWeakRef<Shared, Internal>* weak_ref = node->weak_ref_;
56 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
57  if (weak_ref) {
58 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
59  // get_mutex() returns a shared_ptr copy, so the mutex outlives this lock
60  // even if delete node (below) destroys the WeakRefInternal holding it
61  auto mutex = weak_ref->get_mutex();
62  // Avoid triggering a delete while a weak_ref.shared_if_alive is being called
63  std::lock_guard<std::mutex> lock(*mutex);
64 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
65 
66  if (--static_cast<Internal*>(node)->count == 0) {
67  delete node;
68  node = nullptr;
69  }
70  } else {
71  if (--static_cast<Internal*>(node)->count == 0) {
72  delete node;
73  node = nullptr;
74  }
75  }
76  }
77 
78  template<typename Shared, typename Internal>
79  void GenericShared<Shared, Internal>::own(Internal* node_) {
80  count_down();
81  node = node_;
82  count_up();
83  }
84 
85  template<typename Shared, typename Internal>
86  void GenericShared<Shared, Internal>::assign(Internal* node_) {
87  node = node_;
88  }
89 
90  template<typename Shared, typename Internal>
92  if (node) {
93  return node->debug_repr(node);
94  } else {
95  return "NULL";
96  }
97  }
98 
99  template<typename Shared, typename Internal>
102  // quick return if the old and new pointers point to the same object
103  if (node == ref.node) return *this;
104 
105  // decrease the counter and delete if this was the last pointer
106  count_down();
107 
108  // save the new pointer
109  node = ref.node;
110  count_up();
111  return *this;
112  }
113 
114  template<typename Shared, typename Internal>
115  Internal* GenericShared<Shared, Internal>::get() const {
116  return node;
117  }
118 
119  template<typename Shared, typename Internal>
121  return node==nullptr;
122  }
123 
124  template<typename Shared, typename Internal>
126  casadi_assert_dev(!is_null());
127  return node;
128  }
129 
130  template<typename Shared, typename Internal>
132  GenericShared<Shared, Internal> temp = *this;
133  *this = other;
134  other = temp;
135  }
136 
137  template<typename Shared, typename Internal>
138  casadi_int GenericShared<Shared, Internal>::getCount() const {
139  return (*this)->getCount();
140  }
141 
142  template<typename Shared, typename Internal>
143  GenericWeakRef<Shared, Internal>* GenericShared<Shared, Internal>::weak() {
144  return (*this)->weak();
145  }
146 
147  template<typename Shared, typename Internal>
149  return reinterpret_cast<casadi_int>(get());
150  }
151 
152  template<typename Shared, typename Internal>
154  casadi_assert_dev(dummy==0);
155  }
156 
157  template<typename Shared, typename Internal>
159  return !is_null() && (*this)->raw_ != nullptr;
160  }
161 
162  template<typename Shared, typename Internal>
164  Shared ret;
165  if (alive()) {
166  ret.own((*this)->raw_);
167  }
168  return ret;
169  }
170 
171  template<typename Shared, typename Internal>
173  if (is_null()) return false;
174 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
175  // Safe access to ...
176  std::lock_guard<std::mutex> lock(*(*this)->mutex_);
177 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
178  if (alive()) {
179  shared.own((*this)->raw_);
180  return true;
181  }
182  return false;
183  }
184 
185  template<typename Shared, typename Internal>
186  const GenericWeakRefInternal<Shared, Internal>*
188  return static_cast<const GenericWeakRefInternal<Shared, Internal>*>(
190  }
191 
192  template<typename Shared, typename Internal>
193  GenericWeakRefInternal<Shared, Internal>*
195  return static_cast<GenericWeakRefInternal<Shared, Internal>*>(
197  }
198 
199  template<typename Shared, typename Internal>
201  this->own(shared.weak()->get());
202  }
203 
204  template<typename Shared, typename Internal>
206  this->own(new typename Internal::weak_ref_type(raw));
207  }
208 
209  template<typename Shared, typename Internal>
210  void GenericWeakRef<Shared, Internal>::kill() {
211  casadi_assert_dev((*this)->raw_);
212  (*this)->raw_ = nullptr;
213  }
214 
215 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
216  template<typename Shared, typename Internal>
217  std::shared_ptr<std::mutex> GenericWeakRef<Shared, Internal>::get_mutex() const {
218  return (*this)->mutex_;
219  }
220 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
221 
222 } // namespace casadi
223 
224 
225 #endif // CASADI_GENERIC_SHARED_IMPL_HPP
casadi_int __hash__() const
Returns a number that is unique for a given Node.
std::string debug_repr() const
bool is_null() const
Is a null pointer?
bool alive() const
Check if alive.
Shared shared() const
Get a shared (owning) reference.
GenericWeakRefInternal< Shared, Internal > * operator->()
Access functions of the node.
bool shared_if_alive(Shared &shared) const
Thread-safe alternative to alive()/shared()
GenericWeakRef(int dummy=0)
Default constructor.
The casadi namespace.
Definition: archiver.hpp:32