/usr/share/cruisecontrol-bin-2.6.1/projects/qpid-trunk/cpp/src/qpid/framing/Blob.h

00001 #ifndef QPID_FRAMING_BLOB_H
00002 #define QPID_FRAMING_BLOB_H
00003 
00004 /*
00005  * Licensed to the Apache Software Foundation (ASF) under one
00006  * or more contributor license agreements.  See the NOTICE file
00007  * distributed with this work for additional information
00008  * regarding copyright ownership.  The ASF licenses this file
00009  * to you under the Apache License, Version 2.0 (the
00010  * "License"); you may not use this file except in compliance
00011  * with the License.  You may obtain a copy of the License at
00012  *
00013  *   http://www.apache.org/licenses/LICENSE-2.0
00014  *
00015  * Unless required by applicable law or agreed to in writing,
00016  * software distributed under the License is distributed on an
00017  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
00018  * KIND, either express or implied.  See the License for the
00019  * specific language governing permissions and limitations
00020  * under the License.
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         // Base pointer may be offeset from store.address()
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         b.copy(this->store.address(), b.store.address());
00126         copy = b.copy;
00127         destroy = b.destroy;
00128         basePtr = reinterpret_cast<BaseType*>(
00129             ((char*)this)+ ((char*)(b.basePtr) - (char*)(&b)));
00130     }
00131 
00132   public:
00134     Blob() { initialize(); }
00135 
00137     Blob(const Blob& b) { initialize(); assign(b); }
00138 
00140     template<class InPlace>
00141     Blob(const InPlace & expr, typename EnableInPlace<InPlace>::type* =0) {
00142         initialize(); apply(expr);
00143     }
00144 
00146     template<class T>
00147     Blob(const T & t, typename DisableInPlace<T>::type* =0) {
00148         initialize(); apply(in_place<T>(t));
00149     }
00150 
00151     ~Blob() { clear(); }
00152 
00154     Blob& operator=(const Blob& b) {
00155         clear();
00156         assign(b);
00157         return *this;
00158     }
00159 
00161     template<class InPlace>
00162     typename EnableInPlace<InPlace,Blob&>::type operator=(const InPlace& expr) {
00163         clear(); apply(expr); return *this;
00164     }
00165 
00167     template <class T>
00168     typename DisableInPlace<T, Blob&>::type operator=(const T& x) {
00169         clear(); apply(in_place<T>(x)); return *this;
00170     }
00171 
00173     BaseType* get() { return  basePtr; }
00174 
00176     const BaseType* get() const { return basePtr; }
00177 
00179     void clear() {
00180         void (*oldDestroy)(void*) = destroy; 
00181         initialize();
00182         oldDestroy(store.address());
00183     }
00184 
00185     bool empty() const { return destroy==BlobHelper<void>::destroy; }
00186     
00187     static size_t size() { return Size; }
00188 };
00189 
00190 }} // namespace qpid::framing
00191 
00192 
00193 #endif  

Generated on Thu Apr 10 11:08:18 2008 for Qpid by  doxygen 1.4.7