Lumiera  0.pre.03
»edit your freedom«
scoped-holder.hpp
Go to the documentation of this file.
1 /*
2  SCOPED-HOLDER.hpp - general purpose wrapper for dealing with ownership problems
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
58 #ifndef LIB_SCOPED_HOLDER_H
59 #define LIB_SCOPED_HOLDER_H
60 
61 #include "lib/error.hpp"
62 
63 #include <memory>
64 
65 
66 namespace lib {
67 
68 
69 
70 
76  template<class B>
78  : public std::unique_ptr<B>
79  {
80  typedef std::unique_ptr<B> _Parent;
81 
82  static B* must_be_null (_Parent const& ptr)
83  {
84  if (ptr)
85  throw lumiera::error::Logic("ScopedPtrHolder protocol violation: "
86  "attempt to copy from non-null.");
87  return 0;
88  }
89 
90  public:
92  : _Parent{}
93  { }
94 
95  template<class SU>
96  explicit ScopedPtrHolder (SU * p) // never throws
97  : _Parent(p)
98  { }
99 
100  template<class SU>
101  explicit ScopedPtrHolder (std::unique_ptr<SU> pu) // never throws
102  : _Parent(pu.release())
103  { }
104 
105  ScopedPtrHolder (ScopedPtrHolder const& ref)
106  : _Parent(must_be_null (ref))
107  { }
108 
110  operator= (ScopedPtrHolder const& ref)
111  {
112  must_be_null (*this);
113  must_be_null (ref);
114  return *this;
115  }
116 
117  friend void
118  transfer_control (ScopedPtrHolder& from, ScopedPtrHolder& to)
119  {
120  if (!from) return;
121  TRACE (test, "transfer_control<ScopedPtrHolder>... from=%p to=%p",&from, &to);
122  must_be_null (to);
123  to.swap(from);
124  }
125  };
126 
127 
128 
129 
143  template<class TY>
145  {
146  char content_[sizeof(TY)];
147  char created_;
148 
149 
150  static char
151  must_be_empty (ScopedHolder<TY> const& ref)
152  {
153  if (ref)
154  throw lumiera::error::Logic("ScopedHolder protocol violation: "
155  "copy operation after having invoked create().");
156  return 0;
157  }
158 
159  public:
160  ScopedHolder()
161  : created_(0)
162  { }
163 
164  ~ScopedHolder() { clear(); }
165 
166 
167  TY&
168  create ()
169  {
170  ASSERT (!created_);
171  TY * obj = new(content_) TY();
172  ++created_;
173  return *obj;
174  }
175 
176  TY&
177  create (TY const& o)
178  {
179  ASSERT (!created_);
180  TY * obj = new(content_) TY(o);
181  ++created_;
182  return *obj;
183  }
184 
185  void
186  clear ()
187  {
188  if (created_)
189  get()->~TY();
190  created_ = false;
191  }
192 
193 
194  ScopedHolder (ScopedHolder const& ref)
195  : created_(must_be_empty (ref))
196  { }
197 
198  ScopedHolder&
199  operator= (ScopedHolder const& ref)
200  {
201  must_be_empty (*this);
202  must_be_empty (ref);
203  return *this;
204  }
205 
206 
207  TY&
208  operator* () const
209  {
210  ASSERT (created_);
211  return (TY&) content_;
212  }
213 
214  TY*
215  operator-> () const
216  {
217  ASSERT (created_);
218  return (TY*) &content_;
219  }
220 
221  TY* get() const // never throws
222  {
223  return (TY*) &content_;
224  }
225 
226 
227 
228  explicit operator bool() const { return created_; }
229  bool operator! () const { return not created_; }
230 
231 
232  friend void
233  transfer_control (ScopedHolder& from, ScopedHolder& to)
234  {
235  if (!from) return;
236  TRACE (test, "transfer_control<ScopedHolder>... from=%p to=%p",&from, &to);
237  must_be_empty (to);
238  to.create();
239  try
240  {
241  transfer_control(*from,*to); // note: assumed to have no side-effect in case it throws
242  from.clear();
243  return;
244  }
245  catch(...)
246  {
247  to.clear();
248  WARN (test, "transfer_control operation aborted.");
249  throw;
250  }
251  }
252  };
253 
254 
255 
256 
257 } // namespace lib
258 #endif
Definition: run.hpp:49
Implementation namespace for support and library code.
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:199
Inline buffer holding and owning an object similar to unique_ptr.
TY & create(TY const &o)
Lumiera error handling (C++ interface).
Extension to std::unique_ptr, allowing copy operations on empty pointers (i.e.