1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
5 Copyright (C) 2003, 2004, 2005, 2006, 2007 StatPro Italia srl
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21/*! \file handle.hpp
22 \brief Globally accessible relinkable pointer
23*/
24
25#ifndef quantlib_handle_hpp
26#define quantlib_handle_hpp
27
28#include <ql/patterns/observable.hpp>
29
30namespace QuantLib {
31
32 //! Shared handle to an observable
33 /*! All copies of an instance of this class refer to the same
34 observable by means of a relinkable smart pointer. When such
35 pointer is relinked to another observable, the change will be
36 propagated to all the copies.
37
38 \pre Class T must inherit from Observable
39 */
40 template <class T>
41 class Handle {
42 protected:
43 class Link : public Observable, public Observer {
44 public:
45 explicit Link(const ext::shared_ptr<T>& h,
46 bool registerAsObserver);
47 void linkTo(const ext::shared_ptr<T>&,
48 bool registerAsObserver);
49 bool empty() const { return !h_; }
50 const ext::shared_ptr<T>& currentLink() const { return h_; }
51 void update() override { notifyObservers(); }
52
53 private:
54 ext::shared_ptr<T> h_;
55 bool isObserver_ = false;
56 };
57 ext::shared_ptr<Link> link_;
58 public:
59 /*! \name Constructors
60
61 \warning <tt>registerAsObserver</tt> is left as a backdoor
62 in case the programmer cannot guarantee that the
63 object pointed to will remain alive for the whole
64 lifetime of the handle---namely, it should be set
65 to <tt>false</tt> when the passed shared pointer
66 does not own the pointee (this should only happen
67 in a controlled environment, so that the
68 programmer is aware of it). Failure to do so can
69 very likely result in a program crash. If the
70 programmer does want the handle to register as
71 observer of such a shared pointer, it is his
72 responsibility to ensure that the handle gets
73 destroyed before the pointed object does.
74 */
75 //@{
76 Handle()
77 : Handle(ext::shared_ptr<T>()) {}
78 explicit Handle(const ext::shared_ptr<T>& p,
79 bool registerAsObserver = true)
80 : link_(new Link(p,registerAsObserver)) {}
81 //@}
82 //! dereferencing
83 const ext::shared_ptr<T>& currentLink() const;
84 const ext::shared_ptr<T>& operator->() const;
85 const ext::shared_ptr<T>& operator*() const;
86 //! checks if the contained shared pointer points to anything
87 bool empty() const;
88 //! allows registration as observable
89 operator ext::shared_ptr<Observable>() const;
90 //! equality test
91 template <class U>
92 bool operator==(const Handle<U>& other) const { return link_==other.link_; }
93 //! disequality test
94 template <class U>
95 bool operator!=(const Handle<U>& other) const { return link_!=other.link_; }
96 //! strict weak ordering
97 template <class U>
98 bool operator<(const Handle<U>& other) const { return link_ < other.link_; }
99 };
100
101 //! Relinkable handle to an observable
102 /*! An instance of this class can be relinked so that it points to
103 another observable. The change will be propagated to all
104 handles that were created as copies of such instance.
105
106 \pre Class T must inherit from Observable
107
108 \warning see the Handle documentation for issues
109 relatives to <tt>registerAsObserver</tt>.
110 */
111 template <class T>
112 class RelinkableHandle : public Handle<T> {
113 public:
114 explicit RelinkableHandle(
115 const ext::shared_ptr<T>& p = ext::shared_ptr<T>(),
116 bool registerAsObserver = true);
117 explicit RelinkableHandle(
118 T* p,
119 bool registerAsObserver = true);
120 void linkTo(const ext::shared_ptr<T>&,
121 bool registerAsObserver = true);
122 };
123
124
125 // inline definitions
126
127 template <class T>
128 inline Handle<T>::Link::Link(const ext::shared_ptr<T>& h, bool registerAsObserver) {
129 linkTo(h,registerAsObserver);
130 }
131
132 template <class T>
133 inline void Handle<T>::Link::linkTo(const ext::shared_ptr<T>& h,
134 bool registerAsObserver) {
135 if ((h != h_) || (isObserver_ != registerAsObserver)) {
136 if (h_ && isObserver_)
137 unregisterWith(h: h_);
138 h_ = h;
139 isObserver_ = registerAsObserver;
140 if (h_ && isObserver_)
141 registerWith(h: h_);
142 notifyObservers();
143 }
144 }
145
146
147 template <class T>
148 inline const ext::shared_ptr<T>& Handle<T>::currentLink() const {
149 QL_REQUIRE(!empty(), "empty Handle cannot be dereferenced");
150 return link_->currentLink();
151 }
152
153 template <class T>
154 inline const ext::shared_ptr<T>& Handle<T>::operator->() const {
155 QL_REQUIRE(!empty(), "empty Handle cannot be dereferenced");
156 return link_->currentLink();
157 }
158
159 template <class T>
160 inline const ext::shared_ptr<T>& Handle<T>::operator*() const {
161 QL_REQUIRE(!empty(), "empty Handle cannot be dereferenced");
162 return link_->currentLink();
163 }
164
165 template <class T>
166 inline bool Handle<T>::empty() const {
167 return link_->empty();
168 }
169
170 template <class T>
171 inline Handle<T>::operator ext::shared_ptr<Observable>() const {
172 return link_;
173 }
174
175
176 template <class T>
177 inline RelinkableHandle<T>::RelinkableHandle(const ext::shared_ptr<T>& p,
178 bool registerAsObserver)
179 : Handle<T>(p,registerAsObserver) {}
180
181 template <class T>
182 inline RelinkableHandle<T>::RelinkableHandle(T* p,
183 bool registerAsObserver)
184 : Handle<T>(p,registerAsObserver) {}
185
186 template <class T>
187 inline void RelinkableHandle<T>::linkTo(const ext::shared_ptr<T>& h,
188 bool registerAsObserver) {
189 this->link_->linkTo(h,registerAsObserver);
190 }
191
192}
193
194#endif
195

source code of quantlib/ql/handle.hpp