1    	/* Copyright (c) 2010-2015 Stanford University
2    	 *
3    	 * Permission to use, copy, modify, and distribute this software for any
4    	 * purpose with or without fee is hereby granted, provided that the above
5    	 * copyright notice and this permission notice appear in all copies.
6    	 *
7    	 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
8    	 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9    	 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
10   	 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11   	 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12   	 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13   	 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14   	 */
15   	
16   	#ifndef CEPH_COMMON_TUB_H
17   	#define CEPH_COMMON_TUB_H
18   	
19   	/**
20   	 * A Tub holds an object that may be uninitialized; it allows the allocation of
21   	 * memory for objects to be separated from its construction and destruction.
22   	 * When you initially create a Tub its object is uninitialized (and should not
23   	 * be used). You can call #construct and #destroy to invoke the constructor and
24   	 * destructor of the embedded object, and #get or #operator-> will return the
25   	 * embedded object. The embedded object is automatically destroyed when the Tub
26   	 * is destroyed (if it was ever constructed in the first place).
27   	 *
28   	 * Tubs are useful in situations like the following:
29   	 * - You want to create an array of objects, but the objects need complex
30   	 *   constructors with multiple arguments.
31   	 * - You want to create a collection of objects, only some of which will be
32   	 *   used, and you don't want to pay the cost of constructing objects that will
33   	 *   never be used.
34   	 * - You want automatic destruction of an object but don't want to
35   	 *   heap-allocate the object (as with std::unique_ptr).
36   	 * - You want a way to return failure from a method without using pointers,
37   	 *   exceptions, or special values (e.g. -1). The Tub gives you a 'maybe'
38   	 *   object; it may be empty if a failure occurred.
39   	 * - You want a singleton, but don't want to deal with heap-allocating an
40   	 *   object on first use and freeing it later. Instead, just declare your object
41   	 *   in a tub and do:
42   	 *      if (!tub) tub.construct();
43   	 *  - You want optional arguments to a function, but don't want to use pointers
44   	 *    (i.e. use the Tub's boolean to determine that an argument was passed,
45   	 *    rather than checking arg != NULL).
46   	 *
47   	 * Tub is CopyConstructible if and only if ElementType is CopyConstructible,
48   	 * and Tub is Assignable if and only if ElementType is Assignable.
49   	 *
50   	 * \tparam ElementType
51   	 *      The type of the object to be stored within the Tub.
52   	 */
53   	template<typename ElementType>
54   	class Tub {
55   	 public:
56   	  /// The type of the object to be stored within the Tub.
57   	  typedef ElementType element_type;
58   	
59   	  /**
60   		 * Default constructor: the object starts off uninitialized.
61   		 */
(2) Event uninit_member: Non-static class member field "object._raw" is not initialized in this constructor nor in any functions that it calls.
(4) Event uninit_member: Non-static class member field "object._off" is not initialized in this constructor nor in any functions that it calls.
(6) Event uninit_member: Non-static class member field "object._len" is not initialized in this constructor nor in any functions that it calls.
Also see events: [member_decl][member_decl][member_decl]
62   	  Tub(): occupied(false) {}
63   	
64   	  /**
65   		 * Construct an occupied Tub, whose contained object is initialized
66   		 * with a copy of the given object.
67   		 * \pre
68   		 *      ElementType is CopyConstructible.
69   		 * \param other
70   		 *      Source of the copy.
71   		 */
72   	  Tub(const ElementType& other) // NOLINT
73   	          : occupied(false) {
74   	    construct(other);
75   	  }
76   	
77   	  /**
78   		 * Construct an occupied Tub, whose contained object is initialized
79   		 * with a move of the given object.
80   		 * \pre
81   		 *      ElementType is MoveConstructible.
82   		 * \param other
83   		 *      Source of the move.
84   		 */
85   	  Tub(ElementType&& other) // NOLINT
86   	          : occupied(false) {
87   	    construct(std::move(other));
88   	  }
89   	
90   	  /**
91   		 * Copy constructor.
92   		 * The object will be initialized if and only if the source of the copy is
93   		 * initialized.
94   		 * \pre
95   		 *      ElementType is CopyConstructible.
96   		 * \param other
97   		 *      Source of the copy.
98   		 */
99   	  Tub(const Tub<ElementType>& other) // NOLINT
100  	          : occupied(false) {
101  	    if (other.occupied) {
102  	      construct(*other.object); // use ElementType's copy constructor
103  	    }
104  	  }
105  	
106  	  /**
107  		 * Move constructor.
108  		 * The object will be initialized if and only if the source of the move is
109  		 * initialized.
110  		 * \pre
111  		 *      ElementType is MoveConstructible.
112  		 * \param other
113  		 *      Source of the move.
114  		 */
115  	  Tub(Tub<ElementType>&& other) // NOLINT
116  	          : occupied(false) {
117  	    if (other.occupied)
118  	      construct(std::move(*other.object)); // use ElementType's copy constructor
119  	  }
120  	
121  	  /**
122  		 * Destructor: destroy the object if it was initialized.
123  		 */
124  	  ~Tub() {
125  	    destroy();
126  	  }
127  	
128  	  /**
129  		 * Assignment: destroy current object if initialized, replace with
130  		 * source.  Result will be uninitialized if source is uninitialized.
131  		 * \pre
132  		 *      ElementType is Assignable.
133  		 */
134  	  Tub<ElementType>& operator=(const Tub<ElementType>& other) {
135  	    if (this != &other) {
136  	      if (other.occupied) {
137  	        if (occupied) {
138  	#if __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
139  	          #pragma GCC diagnostic push
140  	#pragma GCC diagnostic ignored "-Warray-bounds"
141  	#endif
142  	          *object = *other.object; // use ElementType's assignment
143  	#if __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 7
144  	#pragma GCC diagnostic pop
145  	#endif
146  	        } else {
147  	          construct(*other.object);
148  	        }
149  	      } else {
150  	        destroy();
151  	      }
152  	    }
153  	    return *this;
154  	  }
155  	
156  	  /**
157  		 * Assignment: destroy current object if initialized, replace with
158  		 * source.  Result will be uninitialized if source is uninitialized.
159  		 * \pre
160  		 *      ElementType is Assignable.
161  		 */
162  	  Tub<ElementType>& operator=(Tub<ElementType> &&other) {
163  	    if (this != &other) {
164  	      if (other.occupied) {
165  	        if (occupied)
166  	          *object = std::move(*other.object);
167  	        else
168  	          construct(std::move(*other.object));
169  	        other.destroy();
170  	      } else {
171  	        destroy();
172  	      }
173  	    }
174  	    return *this;
175  	  }
176  	
177  	  /**
178  		 * Assignment: destroy current object if initialized, replace with
179  		 * source.  Result will be uninitialized if source is uninitialized.
180  		 * \pre
181  		 *      ElementType is Assignable.
182  		 */
183  	  Tub<ElementType>& operator=(ElementType &&elt) {
184  	    if (occupied) {
185  	      *object = std::move(elt);
186  	    } else {
187  	      construct(std::forward<ElementType>(elt));
188  	    }
189  	    return *this;
190  	  }
191  	
192  	  /**
193  		 * Initialize the object.
194  		 * If the object was already initialized, it will be destroyed first.
195  		 * \param args
196  		 *      Arguments to ElementType's constructor.
197  		 * \return
198  		 *      A pointer to the newly initialized object.
199  		 * \post
200  		 *      The object is initialized.
201  		 */
202  	  template<typename... Args>
203  	  ElementType* construct(Args&&... args) {
204  	    destroy();
205  	    new(object) ElementType(std::forward<Args>(args)...);
206  	    occupied = true;
207  	    return object;
208  	  }
209  	
210  	  /**
211  		 * Destroy the object, leaving the Tub in the same state
212  		 * as after the no-argument constructor.
213  		 * If the object was not initialized, this will have no effect.
214  		 * \post
215  		 *      The object is uninitialized.
216  		 */
217  	  void destroy() {
218  	    if (occupied) {
219  	      object->~ElementType();
220  	      occupied = false;
221  	    }
222  	  }
223  	
224  	  /// See #get().
225  	  const ElementType& operator*() const {
226  	    return *get();
227  	  }
228  	
229  	  /// See #get().
230  	  ElementType& operator*() {
231  	    return *get();
232  	  }
233  	
234  	  /// See #get().
235  	  const ElementType* operator->() const {
236  	    return get();
237  	  }
238  	
239  	  /// See #get().
240  	  ElementType* operator->() {
241  	    return get();
242  	  }
243  	
244  	  /**
245  		 * Return a pointer to the object.
246  		 * \pre
247  		 *      The object is initialized.
248  		 */
249  	  ElementType* get() {
250  	    if (!occupied)
251  	      return NULL;
252  	    return object;
253  	  }
254  	
255  	  /// See #get().
256  	  const ElementType* get() const {
257  	    if (!occupied)
258  	      return NULL;
259  	    return object;
260  	  }
261  	
262  	  /**
263  		 * Return whether the object is initialized.
264  		 */
265  	  operator bool() const {
266  	    return occupied;
267  	  }
268  	
269  	 private:
270  	  /**
271  		 * A pointer to where the object is, if it is initialized.
272  		 * This must directly precede #raw in the struct.
273  		 */
274  	  ElementType object[0];
275  	
276  	  /**
277  		 * A storage area to back the object while it is initialized.
278  		 */
279  	  char raw[sizeof(ElementType)];
280  	
281  	  /**
282  		 * Whether the object is initialized.
283  		 */
284  	  bool occupied;
285  	};
286  	
287  	#endif  // CEPH_COMMON_TUB_H
288