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
00031 #include <new>
00032
00033 #include <assert.h>
00034
00035
00036 namespace qpid {
00037 namespace framing {
00038
00039 using boost::in_place;
00040 using boost::typed_in_place_factory_base;
00041
00043 template <class T>
00044 struct typed_in_place_factory0 : public typed_in_place_factory_base {
00045 typedef T value_type ;
00046 void apply ( void* address ) const { new (address) T(); }
00047 };
00048
00050 template<class T>
00051 typed_in_place_factory0<T> in_place() { return typed_in_place_factory0<T>(); }
00052
00053 template <class T, class R=void>
00054 struct EnableInPlace
00055 : public boost::enable_if<boost::is_base_and_derived<
00056 typed_in_place_factory_base, T>,
00057 R>
00058 {};
00059
00060 template <class T, class R=void>
00061 struct DisableInPlace
00062 : public boost::disable_if<boost::is_base_and_derived<
00063 typed_in_place_factory_base, T>,
00064 R>
00065 {};
00066
00067 template <class T> struct BlobHelper {
00068 static void destroy(void* ptr) { static_cast<T*>(ptr)->~T(); }
00069 static void copy(void* dest, const void* src) {
00070 new (dest) T(*static_cast<const T*>(src));
00071 }
00072 };
00073
00074 template <> struct BlobHelper<void> {
00075 static void destroy(void*);
00076 static void copy(void* to, const void* from);
00077 };
00078
00091 template <size_t Size, class BaseType=void>
00092 class Blob
00093 {
00094 boost::aligned_storage<Size> store;
00095 BaseType* basePtr;
00096
00097 void (*destroy)(void*);
00098 void (*copy)(void*, const void*);
00099
00100 template <class T>void setType() {
00101 BOOST_STATIC_ASSERT(sizeof(T) <= Size);
00102 destroy=&BlobHelper<T>::destroy;
00103 copy=&BlobHelper<T>::copy;
00104
00105 basePtr = reinterpret_cast<T*>(store.address());
00106 }
00107
00108 void initialize() {
00109 destroy=&BlobHelper<void>::destroy;
00110 copy=&BlobHelper<void>::copy;
00111 basePtr=0;
00112 }
00113
00114 template<class Factory>
00115 typename EnableInPlace<Factory>::type apply(const Factory& factory)
00116 {
00117 typedef typename Factory::value_type T;
00118 assert(empty());
00119 factory.apply(store.address());
00120 setType<T>();
00121 }
00122
00123 void assign(const Blob& b) {
00124 assert(empty());
00125 if (b.empty()) return;
00126 b.copy(this->store.address(), b.store.address());
00127 copy = b.copy;
00128 destroy = b.destroy;
00129 basePtr = reinterpret_cast<BaseType*>(
00130 ((char*)this)+ ((char*)(b.basePtr) - (char*)(&b)));
00131 }
00132
00133 public:
00135 Blob() { initialize(); }
00136
00138 Blob(const Blob& b) { initialize(); assign(b); }
00139
00141 template<class InPlace>
00142 Blob(const InPlace & expr, typename EnableInPlace<InPlace>::type* =0) {
00143 initialize(); apply(expr);
00144 }
00145
00147 template<class T>
00148 Blob(const T & t, typename DisableInPlace<T>::type* =0) {
00149 initialize(); apply(in_place<T>(t));
00150 }
00151
00152 ~Blob() { clear(); }
00153
00155 Blob& operator=(const Blob& b) {
00156 clear();
00157 assign(b);
00158 return *this;
00159 }
00160
00162 template<class InPlace>
00163 typename EnableInPlace<InPlace,Blob&>::type operator=(const InPlace& expr) {
00164 clear(); apply(expr); return *this;
00165 }
00166
00168 template <class T>
00169 typename DisableInPlace<T, Blob&>::type operator=(const T& x) {
00170 clear(); apply(in_place<T>(x)); return *this;
00171 }
00172
00174 BaseType* get() { return basePtr; }
00175
00177 const BaseType* get() const { return basePtr; }
00178
00180 void clear() {
00181 void (*oldDestroy)(void*) = destroy;
00182 initialize();
00183 oldDestroy(store.address());
00184 }
00185
00186 bool empty() const { return destroy==BlobHelper<void>::destroy; }
00187
00188 static size_t size() { return Size; }
00189 };
00190
00191 }}
00192
00193
00194 #endif