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  if (node->weak_ref_) {
52 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
53  auto mutex = node->weak_ref_->get_mutex();
54  // Avoid triggering a delete while a weak_ref.shared_if_alive is being called
55  std::lock_guard<std::mutex> lock(*mutex);
56  // Could it be that this mutex is destroyed when the lock goes out of scope?
57 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
58 
59  if (--static_cast<Internal*>(node)->count == 0) {
60  delete node;
61  node = nullptr;
62  }
63  } else {
64  if (--static_cast<Internal*>(node)->count == 0) {
65  delete node;
66  node = nullptr;
67  }
68  }
69  }
70 
71  template<typename Shared, typename Internal>
72  void GenericShared<Shared, Internal>::own(Internal* node_) {
73  count_down();
74  node = node_;
75  count_up();
76  }
77 
78  template<typename Shared, typename Internal>
79  void GenericShared<Shared, Internal>::assign(Internal* node_) {
80  node = node_;
81  }
82 
83  template<typename Shared, typename Internal>
85  if (node) {
86  return node->debug_repr(node);
87  } else {
88  return "NULL";
89  }
90  }
91 
92  template<typename Shared, typename Internal>
95  // quick return if the old and new pointers point to the same object
96  if (node == ref.node) return *this;
97 
98  // decrease the counter and delete if this was the last pointer
99  count_down();
100 
101  // save the new pointer
102  node = ref.node;
103  count_up();
104  return *this;
105  }
106 
107  template<typename Shared, typename Internal>
108  Internal* GenericShared<Shared, Internal>::get() const {
109  return node;
110  }
111 
112  template<typename Shared, typename Internal>
114  return node==nullptr;
115  }
116 
117  template<typename Shared, typename Internal>
119  casadi_assert_dev(!is_null());
120  return node;
121  }
122 
123  template<typename Shared, typename Internal>
125  GenericShared<Shared, Internal> temp = *this;
126  *this = other;
127  other = temp;
128  }
129 
130  template<typename Shared, typename Internal>
131  casadi_int GenericShared<Shared, Internal>::getCount() const {
132  return (*this)->getCount();
133  }
134 
135  template<typename Shared, typename Internal>
136  GenericWeakRef<Shared, Internal>* GenericShared<Shared, Internal>::weak() {
137  return (*this)->weak();
138  }
139 
140  template<typename Shared, typename Internal>
142  return reinterpret_cast<casadi_int>(get());
143  }
144 
145  template<typename Shared, typename Internal>
147  casadi_assert_dev(dummy==0);
148  }
149 
150  template<typename Shared, typename Internal>
152  return !is_null() && (*this)->raw_ != nullptr;
153  }
154 
155  template<typename Shared, typename Internal>
157  Shared ret;
158  if (alive()) {
159  ret.own((*this)->raw_);
160  }
161  return ret;
162  }
163 
164  template<typename Shared, typename Internal>
166  if (is_null()) return false;
167 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
168  // Safe access to ...
169  std::lock_guard<std::mutex> lock(*(*this)->mutex_);
170 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
171  if (alive()) {
172  shared.own((*this)->raw_);
173  return true;
174  }
175  return false;
176  }
177 
178  template<typename Shared, typename Internal>
179  const GenericWeakRefInternal<Shared, Internal>*
181  return static_cast<const GenericWeakRefInternal<Shared, Internal>*>(
183  }
184 
185  template<typename Shared, typename Internal>
186  GenericWeakRefInternal<Shared, Internal>*
188  return static_cast<GenericWeakRefInternal<Shared, Internal>*>(
190  }
191 
192  template<typename Shared, typename Internal>
194  this->own(shared.weak()->get());
195  }
196 
197  template<typename Shared, typename Internal>
199  this->own(new typename Internal::weak_ref_type(raw));
200  }
201 
202  template<typename Shared, typename Internal>
203  void GenericWeakRef<Shared, Internal>::kill() {
204  casadi_assert_dev((*this)->raw_);
205  (*this)->raw_ = nullptr;
206  }
207 
208 #ifdef CASADI_WITH_THREADSAFE_SYMBOLICS
209  template<typename Shared, typename Internal>
210  std::shared_ptr<std::mutex> GenericWeakRef<Shared, Internal>::get_mutex() const {
211  return (*this)->mutex_;
212  }
213 #endif // CASADI_WITH_THREADSAFE_SYMBOLICS
214 
215 } // namespace casadi
216 
217 
218 #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