summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-08-09 20:22:10 +0000
committerAlan Conway <aconway@apache.org>2007-08-09 20:22:10 +0000
commit17f7af3557b1a4db846d0521f3652a297a1ef3aa (patch)
tree138b5de6bcfacbe12263d3b45fad14ce6f20c31b /cpp/src
parent0b2a2d6223185b88e69d6fd5b9151276369e0514 (diff)
downloadqpid-python-17f7af3557b1a4db846d0521f3652a297a1ef3aa.tar.gz
Blob: a crude kind of variant that avoids template hell.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@564372 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
-rw-r--r--cpp/src/qpid/framing/Blob.h134
1 files changed, 134 insertions, 0 deletions
diff --git a/cpp/src/qpid/framing/Blob.h b/cpp/src/qpid/framing/Blob.h
new file mode 100644
index 0000000000..5f1fec14bb
--- /dev/null
+++ b/cpp/src/qpid/framing/Blob.h
@@ -0,0 +1,134 @@
+#ifndef QPID_FRAMING_BLOB_H
+#define QPID_FRAMING_BLOB_H
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+#include <boost/aligned_storage.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/utility/typed_in_place_factory.hpp>
+
+#include <new>
+
+#include <assert.h>
+
+
+namespace boost {
+
+/**
+ * Boost doesn't provide the 0 arg version since it assumes
+ * in_place_factory will be used when there is no default ctor.
+ */
+template <class T>
+class typed_in_place_factory0 : public typed_in_place_factory_base {
+ public:
+ typedef T value_type ;
+ void apply ( void* address ) const { new (address) T(); }
+};
+
+template<class T>
+typed_in_place_factory0<T> in_place() { return typed_in_place_factory0<T>(); }
+
+} // namespace boost
+
+namespace qpid {
+namespace framing {
+
+using boost::in_place;
+
+template <class T>
+void destroyT(void* ptr) { static_cast<T*>(ptr)->~T(); }
+void nullDestroy(void*) {}
+
+/**
+ * A "blob" is a chunk of memory which can contain a single object at
+ * a time arbitrary type, provided sizeof(T)<=blob.size(). Blob
+ * ensures proper construction and destruction of its contents,
+ * nothing else.
+ *
+ * In particular the user must ensure the blob is big enough for its
+ * contents and must know the type of object in the blob to cast get().
+ *
+ * Objects can be allocated directly in place using
+ * construct(in_place<T>(...)) or copied using operator=.
+ * Constructing a new object in the blob destroys the old one.
+ */
+template <size_t Size>
+class Blob
+{
+ boost::aligned_storage<Size> store;
+ void (*destroy)(void*);
+
+ template<class TypedInPlaceFactory>
+ void construct (const TypedInPlaceFactory& factory,
+ const boost::typed_in_place_factory_base* )
+ {
+ typedef typename TypedInPlaceFactory::value_type T;
+ assert(sizeof(T) <= Size);
+ clear(); // Destroy old object.
+ factory.apply(store.address());
+ destroy=&destroyT<T>;
+ }
+
+ public:
+ /** Construct an empty blob. */
+ Blob() : destroy(&nullDestroy) {}
+
+ /** @see construct() */
+ template<class Expr>
+ Blob( const Expr & expr ) : destroy(nullDestroy) { construct(expr,&expr); }
+
+ ~Blob() { clear(); }
+
+ /** Construcct an object in the blob. Destroyes the previous object.
+ *@param expr an expresion of the form: in_place<T>(x,y,z)
+ * will construct an object using the constructor T(x,y,z)
+ */
+ template<class Expr> void
+ construct(const Expr& expr) { construct(expr,&expr); }
+
+ /** Copy construct an instance of T into the Blob. */
+ template<class T>
+ Blob& operator=(const T& x) { construct(in_place<T>(x)); }
+
+ /** Get pointer to blob contents. Caller must know how to cast it. */
+ void* get() { return store.address(); }
+
+ /** Get const pointer to blob contents */
+ const void* get() const { return store.address(); }
+
+ /** Destroy the object in the blob making it empty. */
+ void clear() {
+ void (*saveDestroy)(void*) = destroy; // Exception safety
+ destroy = &nullDestroy;
+ saveDestroy(store.address());
+ }
+
+ /** True if there is no object allocated in the blob */
+ bool empty() { return destroy==nullDestroy; }
+
+ static size_t size() { return Size; }
+};
+
+}} // namespace qpid::framing
+
+
+
+#endif /*!QPID_FRAMING_BLOB_H*/