00001 #ifndef QPID_FRAMING_BLOB_H
00002 #define QPID_FRAMING_BLOB_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <boost/static_assert.hpp>
00025 #include <boost/aligned_storage.hpp>
00026 #include <boost/checked_delete.hpp>
00027 #include <boost/utility/typed_in_place_factory.hpp>
00028 #include <boost/type_traits/is_base_and_derived.hpp>
00029 #include <boost/utility/enable_if.hpp>
00030 #include <boost/version.hpp>
00031
00032 #include <new>
00033
00034 #include <assert.h>
00035
00036
00037 namespace qpid {
00038 namespace framing {
00039
00040 using boost::in_place;
00041 using boost::typed_in_place_factory_base;
00042
00044 #if (BOOST_VERSION < 103500)
00045 template <class T>
00046 struct typed_in_place_factory0 : public typed_in_place_factory_base {
00047 typedef T value_type ;
00048 void apply ( void* address ) const { new (address) T(); }
00049 };
00050
00052 template<class T>
00053 typed_in_place_factory0<T> in_place() { return typed_in_place_factory0<T>(); }
00054 #endif
00055
00056 template <class T, class R=void>
00057 struct EnableInPlace
00058 : public boost::enable_if<boost::is_base_and_derived<
00059 typed_in_place_factory_base, T>,
00060 R>
00061 {};
00062
00063 template <class T, class R=void>
00064 struct DisableInPlace
00065 : public boost::disable_if<boost::is_base_and_derived<
00066 typed_in_place_factory_base, T>,
00067 R>
00068 {};
00069
00070 template <class T> struct BlobHelper {
00071 static void destroy(void* ptr) { static_cast<T*>(ptr)->~T(); }
00072 static void copy(void* dest, const void* src) {
00073 new (dest) T(*static_cast<const T*>(src));
00074 }
00075 };
00076
00077 template <> struct BlobHelper<void> {
00078 static void destroy(void*);
00079 static void copy(void* to, const void* from);
00080 };
00081
00094 template <size_t Size, class BaseType=void>
00095 class Blob
00096 {
00097 boost::aligned_storage<Size> store;
00098 BaseType* basePtr;
00099
00100 void (*destroy)(void*);
00101 void (*copy)(void*, const void*);
00102
00103 template <class T>void setType() {
00104 BOOST_STATIC_ASSERT(sizeof(T) <= Size);
00105 destroy=&BlobHelper<T>::destroy;
00106 copy=&BlobHelper<T>::copy;
00107
00108 basePtr = reinterpret_cast<T*>(store.address());
00109 }
00110
00111 void initialize() {
00112 destroy=&BlobHelper<void>::destroy;
00113 copy=&BlobHelper<void>::copy;
00114 basePtr=0;
00115 }
00116
00117 template<class Factory>
00118 typename EnableInPlace<Factory>::type apply(const Factory& factory)
00119 {
00120 typedef typename Factory::value_type T;
00121 assert(empty());
00122 factory.apply(store.address());
00123 setType<T>();
00124 }
00125
00126 void assign(const Blob& b) {
00127 assert(empty());
00128 if (b.empty()) return;
00129 b.copy(this->store.address(), b.store.address());
00130 copy = b.copy;
00131 destroy = b.destroy;
00132 basePtr = reinterpret_cast<BaseType*>(
00133 ((char*)this)+ ((const char*)(b.basePtr) - (const char*)(&b)));
00134 }
00135
00136 public:
00138 Blob() { initialize(); }
00139
00141 Blob(const Blob& b) { initialize(); assign(b); }
00142
00144 template<class InPlace>
00145 Blob(const InPlace & expr, typename EnableInPlace<InPlace>::type* =0) {
00146 initialize(); apply(expr);
00147 }
00148
00150 template<class T>
00151 Blob(const T & t, typename DisableInPlace<T>::type* =0) {
00152 initialize(); apply(in_place<T>(t));
00153 }
00154
00155 ~Blob() { clear(); }
00156
00158 Blob& operator=(const Blob& b) {
00159 clear();
00160 assign(b);
00161 return *this;
00162 }
00163
00165 template<class InPlace>
00166 typename EnableInPlace<InPlace,Blob&>::type operator=(const InPlace& expr) {
00167 clear(); apply(expr); return *this;
00168 }
00169
00171 template <class T>
00172 typename DisableInPlace<T, Blob&>::type operator=(const T& x) {
00173 clear(); apply(in_place<T>(x)); return *this;
00174 }
00175
00177 BaseType* get() { return basePtr; }
00178
00180 const BaseType* get() const { return basePtr; }
00181
00183 void clear() {
00184 void (*oldDestroy)(void*) = destroy;
00185 initialize();
00186 oldDestroy(store.address());
00187 }
00188
00189 bool empty() const { return destroy==BlobHelper<void>::destroy; }
00190
00191 static size_t size() { return Size; }
00192 };
00193
00194 }}
00195
00196
00197 #endif