PROTON-1214: More complex implementation of cached_map with correct ABI
Project: http://git-wip-us.apache.org/repos/asf/qpid-proton/repo Commit: http://git-wip-us.apache.org/repos/asf/qpid-proton/commit/fc82f55b Tree: http://git-wip-us.apache.org/repos/asf/qpid-proton/tree/fc82f55b Diff: http://git-wip-us.apache.org/repos/asf/qpid-proton/diff/fc82f55b Branch: refs/heads/master Commit: fc82f55b89840cb753b53123318c9af14745ab99 Parents: 676a2a8 Author: Andrew Stitcher <[email protected]> Authored: Tue May 24 11:00:29 2016 -0400 Committer: Andrew Stitcher <[email protected]> Committed: Fri May 27 15:18:44 2016 -0400 ---------------------------------------------------------------------- proton-c/bindings/cpp/CMakeLists.txt | 1 + .../cpp/include/proton/internal/cached_map.hpp | 98 +++++++-------- proton-c/bindings/cpp/src/cached_map.cpp | 121 +++++++++++++++++++ 3 files changed, 168 insertions(+), 52 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/fc82f55b/proton-c/bindings/cpp/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/CMakeLists.txt b/proton-c/bindings/cpp/CMakeLists.txt index 983fa8b..18344f4 100644 --- a/proton-c/bindings/cpp/CMakeLists.txt +++ b/proton-c/bindings/cpp/CMakeLists.txt @@ -30,6 +30,7 @@ set(qpid-proton-cpp-source src/acceptor.cpp src/binary.cpp src/byte_array.cpp + src/cached_map.cpp src/connection.cpp src/connection_options.cpp src/connector.cpp http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/fc82f55b/proton-c/bindings/cpp/include/proton/internal/cached_map.hpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/include/proton/internal/cached_map.hpp b/proton-c/bindings/cpp/include/proton/internal/cached_map.hpp index ced52c6..f7b7c26 100644 --- a/proton-c/bindings/cpp/include/proton/internal/cached_map.hpp +++ b/proton-c/bindings/cpp/include/proton/internal/cached_map.hpp @@ -22,72 +22,66 @@ * */ -#include "../value.hpp" -#include "../codec/decoder.hpp" -#include "../codec/encoder.hpp" - #include "./config.hpp" +#include "./export.hpp" #include "./pn_unique_ptr.hpp" -#include <map> +#include <cstddef> namespace proton { + +namespace codec { +class decoder; +class encoder; +} + namespace internal { +template <class key_type, class value_type> +class map_type_impl; + /// A convenience class to view and manage AMQP map data contained in /// a proton::value. An internal cache of the map data is created as -/// needed. If desired, a std::map can be extracted from or inserted -/// into the cached_map value directly. +/// needed. +template <class K, class V> +class cached_map; + +template <class K, class V> +PN_CPP_EXTERN proton::codec::decoder& operator>>(proton::codec::decoder& d, cached_map<K,V>& m); +template <class K, class V> +PN_CPP_EXTERN proton::codec::encoder& operator<<(proton::codec::encoder& e, const cached_map<K,V>& m); + template <class key_type, class value_type> -class cached_map { - typedef std::map<key_type, value_type> map_type; - public: +class PN_CPP_CLASS_EXTERN cached_map { + typedef map_type_impl<key_type, value_type> map_type; -#if PN_CPP_HAS_DEFAULTED_FUNCTIONS - cached_map() = default; - cached_map(const cached_map&) = default; - cached_map& operator=(const cached_map&) = default; - cached_map(cached_map&&) = default; - cached_map& operator=(cached_map&&) = default; - ~cached_map() = default; + public: + PN_CPP_EXTERN cached_map(); + PN_CPP_EXTERN cached_map(const cached_map& cm); + PN_CPP_EXTERN cached_map& operator=(const cached_map& cm); +#if PN_CPP_HAS_RVALUE_REFERENCES + PN_CPP_EXTERN cached_map(cached_map&&); + PN_CPP_EXTERN cached_map& operator=(cached_map&&); #endif + PN_CPP_EXTERN ~cached_map(); - value_type get(const key_type& k) const { - typename map_type::const_iterator i = map_.find(k); - if ( i==map_.end() ) return value_type(); - return i->second; - } - void put(const key_type& k, const value_type& v) { - map_[k] = v; - } - size_t erase(const key_type& k) { - return map_.erase(k); - } - bool exists(const key_type& k) const { - return map_.count(k) > 0; - } - - size_t size() { - return map_.size(); - } - void clear() { - map_.clear(); - } - bool empty() { - return map_.empty(); - } - - /// @cond INTERNAL + PN_CPP_EXTERN value_type get(const key_type& k) const; + PN_CPP_EXTERN void put(const key_type& k, const value_type& v); + PN_CPP_EXTERN size_t erase(const key_type& k); + PN_CPP_EXTERN bool exists(const key_type& k) const; + PN_CPP_EXTERN size_t size(); + PN_CPP_EXTERN void clear(); + PN_CPP_EXTERN bool empty(); + + /// @cond INTERNAL private: - map_type map_; - /// @endcond - - friend proton::codec::decoder& operator>>(proton::codec::decoder& d, cached_map& m) { - return d >> m.map_; - } - friend proton::codec::encoder& operator<<(proton::codec::encoder& e, const cached_map& m) { - return e << m.map_; - } + pn_unique_ptr<map_type> map_; + + void make_cached_map(); + + friend PN_CPP_EXTERN proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cached_map<key_type, value_type>& m); + friend PN_CPP_EXTERN proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cached_map<key_type, value_type>& m); + /// @endcond }; http://git-wip-us.apache.org/repos/asf/qpid-proton/blob/fc82f55b/proton-c/bindings/cpp/src/cached_map.cpp ---------------------------------------------------------------------- diff --git a/proton-c/bindings/cpp/src/cached_map.cpp b/proton-c/bindings/cpp/src/cached_map.cpp new file mode 100644 index 0000000..50191eb --- /dev/null +++ b/proton-c/bindings/cpp/src/cached_map.cpp @@ -0,0 +1,121 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +#include "proton/internal/cached_map.hpp" + +#include "proton/annotation_key.hpp" +#include "proton/scalar.hpp" +#include "proton/value.hpp" +#include "proton/codec/decoder.hpp" +#include "proton/codec/encoder.hpp" +#include "proton/codec/map.hpp" + +#include <map> +#include <string> + +namespace proton { +namespace internal { + + // use std::map as the actual cached_map implementation type +template <class K, class V> +class map_type_impl : public std::map<K, V> {}; + +template <class K, class V> +cached_map<K,V>::cached_map() {} +template <class K, class V> +cached_map<K,V>::cached_map(const cached_map& cm) { if ( !cm.map_ ) return; map_type nm(*cm.map_); map_.reset(&nm); } +template <class K, class V> +cached_map<K,V>& cached_map<K,V>::operator=(const cached_map& cm) { if (!!cm.map_ ) { map_type nm(*cm.map_); map_.reset(&nm); } return *this; } +template <class K, class V> +#if PN_CPP_HAS_RVALUE_REFERENCES +cached_map<K,V>::cached_map(cached_map&& cm) : map_(std::move(cm.map_)) {} +template <class K, class V> +cached_map<K,V>& cached_map<K,V>::operator=(cached_map&& cm) { map_.reset(cm.map_.release()); return *this; } +template <class K, class V> +#endif +cached_map<K,V>::~cached_map() {} + +template <class K, class V> +V cached_map<K,V>::get(const K& k) const { + if ( !map_ ) return V(); + typename map_type::const_iterator i = map_->find(k); + if ( i==map_->end() ) return V(); + return i->second; +} +template <class K, class V> +void cached_map<K,V>::put(const K& k, const V& v) { + if ( !map_ ) make_cached_map(); + (*map_)[k] = v; +} +template <class K, class V> +size_t cached_map<K,V>::erase(const K& k) { + if ( !map_ ) return 0; + return map_->erase(k); +} +template <class K, class V> +bool cached_map<K,V>::exists(const K& k) const { + if ( !map_ ) return false; + return map_->count(k) > 0; +} + +template <class K, class V> +size_t cached_map<K,V>::size() { + if ( !map_ ) return 0; + return map_->size(); +} +template <class K, class V> +void cached_map<K,V>::clear() { + map_.reset(); +} +template <class K, class V> +bool cached_map<K,V>::empty() { + if ( !map_ ) return true; + return map_->empty(); +} + +template <class K, class V> +void cached_map<K,V>::make_cached_map() { map_.reset(new map_type); } + +template <class K, class V> +PN_CPP_EXTERN proton::codec::decoder& operator>>(proton::codec::decoder& d, cached_map<K,V>& m) { + if ( !m.map_ ) m.make_cached_map(); + return d >> *(m.map_); +} +template <class K, class V> +PN_CPP_EXTERN proton::codec::encoder& operator<<(proton::codec::encoder& e, const cached_map<K,V>& m) { + if ( !m.map_ ) return e; + return e << *(m.map_); +} + +// Force the necessary template instantiations so that the library exports the correct symbols +template class PN_CPP_CLASS_EXTERN cached_map<std::string, scalar>; +template class PN_CPP_CLASS_EXTERN cached_map<annotation_key, value>; +template class PN_CPP_CLASS_EXTERN cached_map<symbol, value>; + +template proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cached_map<std::string, scalar>& m); +template proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cached_map<std::string, scalar>& m); +template proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cached_map<annotation_key, value>& m); +template proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cached_map<annotation_key, value>& m); +template proton::codec::decoder& operator>> <>(proton::codec::decoder& d, cached_map<symbol, value>& m); +template proton::codec::encoder& operator<< <>(proton::codec::encoder& e, const cached_map<symbol, value>& m); + +} +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
