summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/framing
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-08-20 17:18:52 +0000
committerAlan Conway <aconway@apache.org>2007-08-20 17:18:52 +0000
commit16db1cb57501363fea65127cb5eee797399305ac (patch)
tree0cb547b44e87d5d7eaafb9923b28fe6806700990 /cpp/src/qpid/framing
parent6cc9fa34792b640df3283f4aa4021237f2ee4ae9 (diff)
downloadqpid-python-16db1cb57501363fea65127cb5eee797399305ac.tar.gz
Fixed Blob bug causing test crashes/hangs.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@567755 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/framing')
-rw-r--r--cpp/src/qpid/framing/Blob.cpp1
-rw-r--r--cpp/src/qpid/framing/Blob.h56
-rw-r--r--cpp/src/qpid/framing/MethodHolder.cpp4
-rw-r--r--cpp/src/qpid/framing/MethodHolder.h2
4 files changed, 39 insertions, 24 deletions
diff --git a/cpp/src/qpid/framing/Blob.cpp b/cpp/src/qpid/framing/Blob.cpp
index 0aaeb4138e..388d4b64ef 100644
--- a/cpp/src/qpid/framing/Blob.cpp
+++ b/cpp/src/qpid/framing/Blob.cpp
@@ -25,6 +25,7 @@ namespace qpid {
namespace framing {
void BlobHelper<void>::destroy(void*) {}
+
void BlobHelper<void>::copy(void*, const void*) {}
}} // namespace qpid::framing
diff --git a/cpp/src/qpid/framing/Blob.h b/cpp/src/qpid/framing/Blob.h
index ea44dc104e..9d0c33dee6 100644
--- a/cpp/src/qpid/framing/Blob.h
+++ b/cpp/src/qpid/framing/Blob.h
@@ -21,6 +21,7 @@
*
*/
+#include <boost/static_assert.hpp>
#include <boost/aligned_storage.hpp>
#include <boost/checked_delete.hpp>
#include <boost/utility/typed_in_place_factory.hpp>
@@ -80,47 +81,62 @@ template <> struct BlobHelper<void> {
* 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.
+ *
+ * If BaseType is specified then only object that can be
+ * safely static_cast to BaseType may be stored in the Blob.
*/
-template <size_t Size>
+template <size_t Size, class BaseType=void>
class Blob
{
boost::aligned_storage<Size> store;
+ BaseType* basePtr;
+
void (*destroy)(void*);
void (*copy)(void*, const void*);
- template <class T> void setType() {
+ template <class T>void setType() {
+ BOOST_STATIC_ASSERT(sizeof(T) <= Size);
destroy=&BlobHelper<T>::destroy;
copy=&BlobHelper<T>::copy;
+ // Base pointer may be offeset from store.address()
+ basePtr = reinterpret_cast<T*>(store.address());
}
-
+
+ void initialize() {
+ destroy=&BlobHelper<void>::destroy;
+ copy=&BlobHelper<void>::copy;
+ basePtr=0;
+ }
+
template<class TypedInPlaceFactory>
void construct (const TypedInPlaceFactory& factory,
const boost::typed_in_place_factory_base* )
{
- assert(empty());
typedef typename TypedInPlaceFactory::value_type T;
- assert(sizeof(T) <= Size);
+ assert(empty());
factory.apply(store.address());
setType<T>();
}
void assign(const Blob& b) {
assert(empty());
- b.copy(this->get(), b.get());
+ b.copy(this->store.address(), b.store.address());
copy = b.copy;
destroy = b.destroy;
+ basePtr = reinterpret_cast<BaseType*>(
+ ((char*)this)+ ((char*)(b.basePtr) - (char*)(&b)));
}
-
+
public:
/** Construct an empty blob. */
- Blob() { setType<void>(); }
+ Blob() { initialize(); }
/** Copy a blob. */
- Blob(const Blob& b) { setType<void>(); assign(b); }
+ Blob(const Blob& b) { initialize(); assign(b); }
/** @see construct() */
template<class Expr>
- Blob( const Expr & expr ) { setType<void>(); construct(expr,&expr); }
+ Blob( const Expr & expr ) { initialize(); construct(expr,&expr); }
~Blob() { clear(); }
@@ -139,30 +155,28 @@ class Blob
construct(const Expr& expr) { clear(); construct(expr,&expr); }
/** Copy construct an instance of T into the Blob. */
- template<class T>
+ template <class T>
Blob& operator=(const T& x) { clear(); construct(in_place<T>(x)); return *this; }
-
- /** 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 empty() ? 0 : store.address(); }
-
+ /** Get pointer to blob contents, returns 0 if empty. */
+ BaseType* get() { return basePtr; }
+
+ /** Get pointer to blob contents, returns 0 if empty. */
+ const BaseType* get() const { return basePtr; }
+
/** Destroy the object in the blob making it empty. */
void clear() {
void (*oldDestroy)(void*) = destroy;
- setType<void>();
+ initialize();
oldDestroy(store.address());
}
- bool empty() const { return destroy == BlobHelper<void>::destroy; }
+ bool empty() const { return destroy==BlobHelper<void>::destroy; }
static size_t size() { return Size; }
};
-
}} // namespace qpid::framing
-
#endif /*!QPID_FRAMING_BLOB_H*/
diff --git a/cpp/src/qpid/framing/MethodHolder.cpp b/cpp/src/qpid/framing/MethodHolder.cpp
index b1582dd571..691d556ade 100644
--- a/cpp/src/qpid/framing/MethodHolder.cpp
+++ b/cpp/src/qpid/framing/MethodHolder.cpp
@@ -32,11 +32,11 @@ namespace qpid {
namespace framing {
AMQMethodBody* MethodHolder::get() {
- return static_cast<AMQMethodBody*>(blob.get());
+ return blob.get();
}
const AMQMethodBody* MethodHolder::get() const {
- return const_cast<MethodHolder*>(this)->get();
+ return blob.get();
}
void MethodHolder::encode(Buffer& b) const {
diff --git a/cpp/src/qpid/framing/MethodHolder.h b/cpp/src/qpid/framing/MethodHolder.h
index a8bc8f2728..5324b34ccd 100644
--- a/cpp/src/qpid/framing/MethodHolder.h
+++ b/cpp/src/qpid/framing/MethodHolder.h
@@ -84,7 +84,7 @@ class MethodHolder
bool empty() const { return blob.empty(); }
private:
- Blob<MAX_METHODBODY_SIZE> blob;
+ Blob<MAX_METHODBODY_SIZE, AMQMethodBody> blob;
class CopyVisitor;
friend struct CopyVisitor;
};