You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ac...@apache.org on 2007/11/10 03:43:29 UTC

svn commit: r593721 - in /incubator/qpid/trunk/qpid/cpp/src/qpid/framing: AMQHeaderBody.cpp AMQHeaderBody.h

Author: aconway
Date: Fri Nov  9 18:43:26 2007
New Revision: 593721

URL: http://svn.apache.org/viewvc?rev=593721&view=rev
Log:

Replace vector in AMQHeaderBody with boost::optional.
Eliminates 40% of allocs.

Modified:
    incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp
    incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.h

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp?rev=593721&r1=593720&r2=593721&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.cpp Fri Nov  9 18:43:26 2007
@@ -22,36 +22,21 @@
 #include "qpid/Exception.h"
 #include "qpid/log/Statement.h"
 
-qpid::framing::AMQHeaderBody::AMQHeaderBody() {}
-
-qpid::framing::AMQHeaderBody::~AMQHeaderBody() {}
-
-uint32_t qpid::framing::AMQHeaderBody::size() const{
-    CalculateSize visitor;
-    for_each(properties.begin(), properties.end(), boost::apply_visitor(visitor));
-    return visitor.totalSize();
+uint32_t qpid::framing::AMQHeaderBody::size() const {
+    return properties.size();
 }
 
 void qpid::framing::AMQHeaderBody::encode(Buffer& buffer) const {
-    Encode visitor(buffer);
-    for_each(properties.begin(), properties.end(), boost::apply_visitor(visitor));
+    properties.encode(buffer);
 }
 
-void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t size){
+void qpid::framing::AMQHeaderBody::decode(Buffer& buffer, uint32_t size) {
     uint32_t limit = buffer.available() - size;
     while (buffer.available() > limit + 2) {
         uint32_t len = buffer.getLong();
         uint16_t type = buffer.getShort();
-        //The following switch could be generated as the number of options increases:
-        switch(type) {
-        case MessageProperties::TYPE:
-            decode(MessageProperties(), buffer, len - 2);
-            break;
-        case DeliveryProperties::TYPE:
-            decode(DeliveryProperties(), buffer, len - 2);
-            break;
-        default:
-            //TODO: should just skip over them keeping them for later dispatch as is
+        if (!properties.decode(buffer, len, type)) {
+            // TODO: should just skip & keep for later dispatch.
             throw Exception(QPID_MSG("Unexpected property type: " << type));
         }
     }
@@ -60,9 +45,8 @@
 uint64_t qpid::framing::AMQHeaderBody::getContentLength() const
 {    
     const MessageProperties* mProps = get<MessageProperties>();
-    if (mProps) {
+    if (mProps) 
         return mProps->getContentLength();
-    }
     return 0;
 }
 
@@ -70,7 +54,10 @@
 {
     out << "header (" << size() << " bytes)";
     out << "; properties={";
-    Print visitor(out);
-    for_each(properties.begin(), properties.end(), boost::apply_visitor(visitor));
+    properties.print(out);
     out << "}";
+}
+
+void qpid::framing::AMQHeaderBody::accept(AMQBodyConstVisitor& v) const {
+    v.visit(*this);
 }

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.h?rev=593721&r1=593720&r2=593721&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/framing/AMQHeaderBody.h Fri Nov  9 18:43:26 2007
@@ -1,3 +1,6 @@
+#ifndef QPID_FRAMING_AMQHEADERBODY_H
+#define QPID_FRAMING_AMQHEADERBODY_H
+
 /*
  *
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -24,66 +27,58 @@
 #include "qpid/framing/DeliveryProperties.h"
 #include "qpid/framing/MessageProperties.h"
 #include <iostream>
-#include <vector>
-#include <boost/variant.hpp>
-#include <boost/variant/get.hpp>
 
-#ifndef _AMQHeaderBody_
-#define _AMQHeaderBody_
+#include <boost/optional.hpp>
+
 
 namespace qpid {
 namespace framing {
 
 class AMQHeaderBody :  public AMQBody
 {
-    typedef std::vector< boost::variant<DeliveryProperties, MessageProperties> > PropertyList; 
-
-    PropertyList properties;
-
-    template <class T> void decode(T t, Buffer& b, uint32_t size) {
-        t.decodeStructBody(b, size);
-        properties.push_back(t);
-    }
-
-    class Encode : public boost::static_visitor<> {
-        Buffer& buffer;
-    public:
-        Encode(Buffer& b) : buffer(b) {}
-
-        template <class T> void operator()(T& t) const {
-            t.encode(buffer);
-        }
-
-    };
-
-    class CalculateSize : public boost::static_visitor<> {
-        uint32_t size;
-    public:
-        CalculateSize() : size(0) {}
-
-        template <class T> void operator()(T& t) {
-            size += t.size();
+    template <class T> struct OptProps { boost::optional<T> props; };
+    template <class Base, class T>
+    struct PropSet : public Base, public OptProps<T> {
+        uint32_t size() const {
+            const boost::optional<T>& p=this->OptProps<T>::props;
+            return (p ? p->size() : 0) + Base::size();
+        }
+        void encode(Buffer& buffer) const {
+            const boost::optional<T>& p=this->OptProps<T>::props;
+            if (p) p->encode(buffer);
+            Base::encode(buffer);
+        }
+        bool decode(Buffer& buffer, uint32_t size, uint16_t type) {
+            boost::optional<T>& p=this->OptProps<T>::props;
+            if (type == T::TYPE) {
+                p=T();
+                p->decodeStructBody(buffer, size);
+                return true;
         }
-
-        uint32_t totalSize() { 
-            return size; 
+            else
+                return Base::decode(buffer, size, type);
         }        
+        void print(std::ostream& out) const {
+            const boost::optional<T>& p=this->OptProps<T>::props;
+            Base::print(out << p);
+        }
     };
 
-    class Print : public boost::static_visitor<> {
-        std::ostream& out;
-    public:
-        Print(std::ostream& o) : out(o) {}
-
-        template <class T> void operator()(T& t) {
-            out << t;
-        }
+    struct Empty {
+        uint32_t size() const { return 0; }
+        void encode(Buffer&) const {};
+        bool decode(Buffer&, uint32_t, uint16_t) const { return false; };
+        void print(std::ostream&) const {}
     };
 
+    // Could use boost::mpl::fold to construct a larger set.
+    typedef PropSet<PropSet<Empty, DeliveryProperties>,
+                    MessageProperties> Properties;
+
+    Properties properties;
+    
 public:
 
-    AMQHeaderBody();
-    ~AMQHeaderBody();
     inline uint8_t type() const { return HEADER_BODY; }
 
     uint32_t size() const;
@@ -91,33 +86,21 @@
     void decode(Buffer& buffer, uint32_t size);
     uint64_t getContentLength() const;
     void print(std::ostream& out) const;
+    void accept(AMQBodyConstVisitor&) const;
 
-    void accept(AMQBodyConstVisitor& v) const { v.visit(*this); }
-
-    template <class T> T* get(bool create) { 
-        for (PropertyList::iterator i = properties.begin(); i != properties.end(); i++) {
-            T* p = boost::get<T>(&(*i));
-            if (p) return p;
-        }
-        if (create) {
-            properties.push_back(T());
-            return boost::get<T>(&(properties.back()));
-        } else {
-            return 0;
-        }
+    template <class T> T* get(bool create) {
+        boost::optional<T>& p=properties.OptProps<T>::props;
+        if (create && !p) p=T();
+        return p.get_ptr();
     }
 
-    template <class T> const T* get() const { 
-        for (PropertyList::const_iterator i = properties.begin(); i != properties.end(); i++) {
-            const T* p = boost::get<T>(&(*i));
-            if (p) return p;
-        }
-        return 0;
+    template <class T> const T* get() const {
+        return properties.OptProps<T>::props.get_ptr();
     }
 };
 
-}
-}
+}}
+
 
 
-#endif
+#endif  /*!QPID_FRAMING_AMQHEADERBODY_H*/