diff options
| author | Alan Conway <aconway@apache.org> | 2009-05-01 14:53:05 +0000 |
|---|---|---|
| committer | Alan Conway <aconway@apache.org> | 2009-05-01 14:53:05 +0000 |
| commit | dd79366789a749856de0e41633146340c2b79f9a (patch) | |
| tree | 69e792e992a3071a19c112d6bd9d715f4ce1d27e /cpp/src | |
| parent | db687f6ce97fe987936711f9c46966d45cf24834 (diff) | |
| download | qpid-python-dd79366789a749856de0e41633146340c2b79f9a.tar.gz | |
Cleaned up PIMPL pattern for public API
- Separated PrivateImplRef helper classs from Handler base class.
- Consistent impl of ctor, dtor, copy, assign for all PIMPL classes.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@770702 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src')
| -rw-r--r-- | cpp/src/Makefile.am | 4 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Completion.cpp | 12 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Completion.h | 22 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Handle.h | 23 | ||||
| -rw-r--r-- | cpp/src/qpid/client/HandleAccess.h | 41 | ||||
| -rw-r--r-- | cpp/src/qpid/client/HandlePrivate.h | 67 | ||||
| -rw-r--r-- | cpp/src/qpid/client/LocalQueue.cpp | 7 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Message.cpp | 16 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Message.h | 18 | ||||
| -rw-r--r-- | cpp/src/qpid/client/MessageImpl.h | 6 | ||||
| -rw-r--r-- | cpp/src/qpid/client/PrivateImpl.h | 54 | ||||
| -rw-r--r-- | cpp/src/qpid/client/PrivateImplPrivate.h | 66 | ||||
| -rw-r--r-- | cpp/src/qpid/client/PrivateImplRef.h | 93 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Subscription.cpp | 8 | ||||
| -rw-r--r-- | cpp/src/qpid/client/Subscription.h | 11 | ||||
| -rw-r--r-- | cpp/src/qpid/client/SubscriptionImpl.cpp | 7 | ||||
| -rw-r--r-- | cpp/src/qpid/client/TypedResult.h | 2 |
17 files changed, 178 insertions, 279 deletions
diff --git a/cpp/src/Makefile.am b/cpp/src/Makefile.am index 457463e72d..c1b68a8f50 100644 --- a/cpp/src/Makefile.am +++ b/cpp/src/Makefile.am @@ -449,8 +449,6 @@ libqpidclient_la_SOURCES = \ qpid/client/Completion.cpp \ qpid/client/CompletionImpl.h \ qpid/client/FutureResult.cpp \ - qpid/client/HandlePrivate.h \ - qpid/client/PrivateImplPrivate.h \ qpid/client/LoadPlugins.cpp \ qpid/client/LocalQueue.cpp \ qpid/client/Message.cpp \ @@ -601,7 +599,7 @@ nobase_include_HEADERS = \ qpid/client/FutureCompletion.h \ qpid/client/FutureResult.h \ qpid/client/Handle.h \ - qpid/client/PrivateImpl.h \ + qpid/client/PrivateImplRef.h \ qpid/client/LocalQueue.h \ qpid/client/QueueOptions.h \ qpid/client/Message.h \ diff --git a/cpp/src/qpid/client/Completion.cpp b/cpp/src/qpid/client/Completion.cpp index e3676b2bde..a57eb29d04 100644 --- a/cpp/src/qpid/client/Completion.cpp +++ b/cpp/src/qpid/client/Completion.cpp @@ -21,15 +21,17 @@ #include "Completion.h" #include "CompletionImpl.h" -#include "HandlePrivate.h" +#include "PrivateImplRef.h" namespace qpid { namespace client { -Completion::Completion(CompletionImpl* i) : Handle<CompletionImpl>(i) {} -Completion::~Completion() {} -Completion::Completion(const Completion& c) : Handle<CompletionImpl>(c.impl) {} -Completion& Completion::operator=(const Completion& c) { Handle<CompletionImpl>::operator=(c); return *this; } +typedef PrivateImplRef<Completion> PI; +Completion::Completion(CompletionImpl* p) { PI::ctor(*this, p); } +Completion::Completion(const Completion& c) : Handle<CompletionImpl>() { PI::copy(*this, c); } +Completion::~Completion() { PI::dtor(*this); } +Completion& Completion::operator=(const Completion& c) { return PI::assign(*this, c); } + void Completion::wait() { impl->wait(); } bool Completion::isComplete() { return impl->isComplete(); } diff --git a/cpp/src/qpid/client/Completion.h b/cpp/src/qpid/client/Completion.h index 0b246b7765..d28cfac52a 100644 --- a/cpp/src/qpid/client/Completion.h +++ b/cpp/src/qpid/client/Completion.h @@ -1,3 +1,6 @@ +#ifndef QPID_CLIENT_COMPLETION_H +#define QPID_CLIENT_COMPLETION_H + /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,16 +22,15 @@ * */ -#ifndef _Completion_ -#define _Completion_ - #include "Handle.h" +#include "ClientImportExport.h" #include <string> namespace qpid { namespace client { class CompletionImpl; +template <class T> class PrivateImplRef; /** * Asynchronous commands that do not return a result will return a @@ -42,10 +44,9 @@ class CompletionImpl; class Completion : public Handle<CompletionImpl> { public: - ///@internal - QPID_CLIENT_EXTERN Completion(CompletionImpl* =0); - QPID_CLIENT_EXTERN ~Completion(); + QPID_CLIENT_EXTERN Completion(CompletionImpl* = 0); QPID_CLIENT_EXTERN Completion(const Completion&); + QPID_CLIENT_EXTERN ~Completion(); QPID_CLIENT_EXTERN Completion& operator=(const Completion&); /** Wait for the asynchronous command that returned this @@ -54,13 +55,18 @@ public: *@exception If the command returns an error. */ QPID_CLIENT_EXTERN void wait(); - QPID_CLIENT_EXTERN bool isComplete(); protected: QPID_CLIENT_EXTERN std::string getResult(); + + private: + typedef CompletionImpl Impl; + Impl* impl; + friend class PrivateImplRef<Completion>; }; }} -#endif + +#endif /*!QPID_CLIENT_COMPLETION_H*/ diff --git a/cpp/src/qpid/client/Handle.h b/cpp/src/qpid/client/Handle.h index 12fb4cf3c1..41ead78eb7 100644 --- a/cpp/src/qpid/client/Handle.h +++ b/cpp/src/qpid/client/Handle.h @@ -27,10 +27,10 @@ namespace qpid { namespace client { -template <class T> class HandlePrivate; +template <class> class PrivateImplRef; /** - * A handle is like a pointer: it points to some implementation object. + * A handle is like a pointer: refers to an underlying implementation object. * Copying the handle does not copy the object. * * Handles can be null, like a 0 pointer. Use isValid(), isNull() or the @@ -38,9 +38,6 @@ template <class T> class HandlePrivate; */ template <class T> class Handle { public: - QPID_CLIENT_EXTERN ~Handle(); - QPID_CLIENT_EXTERN Handle(const Handle&); - QPID_CLIENT_EXTERN Handle& operator=(const Handle&); /**@return true if handle is valid, i.e. not null. */ QPID_CLIENT_EXTERN bool isValid() const { return impl; } @@ -54,13 +51,19 @@ template <class T> class Handle { /** Operator ! supports idiom if (!handle) { do_if_handle_is_null(); } */ QPID_CLIENT_EXTERN bool operator !() const { return !impl; } - QPID_CLIENT_EXTERN void swap(Handle<T>&); - + void swap(Handle<T>& h) { T* t = h.impl; h.impl = impl; impl = t; } + protected: - QPID_CLIENT_EXTERN Handle(T* =0); - T* impl; + typedef T Impl; + QPID_CLIENT_EXTERN Handle() :impl() {} + + // Not implemented,subclasses must implement. + QPID_CLIENT_EXTERN Handle(const Handle&); + QPID_CLIENT_EXTERN Handle& operator=(const Handle&); + + Impl* impl; - friend class HandlePrivate<T>; + friend class PrivateImplRef<T>; // FIXME aconway 2009-04-30: Specify }; }} // namespace qpid::client diff --git a/cpp/src/qpid/client/HandleAccess.h b/cpp/src/qpid/client/HandleAccess.h deleted file mode 100644 index f1747db638..0000000000 --- a/cpp/src/qpid/client/HandleAccess.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef QPID_CLIENT_HANDLEACCESS_H -#define QPID_CLIENT_HANDLEACCESS_H - -/* - * - * 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 <Handle.h> - -namespace qpid { -namespace client { - -/** - * Provide access to the private impl member of a Handle. - */ -template <class T> -class HandleAccess -{ - public: - static boost::shared_ptr<T> getImpl(Handle<T>& h) { return h.impl; } -}; -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_HANDLEACCESS_H*/ diff --git a/cpp/src/qpid/client/HandlePrivate.h b/cpp/src/qpid/client/HandlePrivate.h deleted file mode 100644 index 46e4bff808..0000000000 --- a/cpp/src/qpid/client/HandlePrivate.h +++ /dev/null @@ -1,67 +0,0 @@ -#ifndef QPID_CLIENT_HANDLEPRIVATE_H -#define QPID_CLIENT_HANDLEPRIVATE_H - -/* - * - * 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 "Handle.h" -#include "qpid/RefCounted.h" -#include <algorithm> -#include <boost/intrusive_ptr.hpp> - -namespace qpid { -namespace client { - -/** @file - * Implementation of handle, include in .cpp file of handle subclasses. - * T can be any class that can be used with boost::intrusive_ptr. - */ - -template <class T> -Handle<T>::Handle(T* p) : impl(p) { if (impl) boost::intrusive_ptr_add_ref(impl); } - -template <class T> -Handle<T>::~Handle() { if(impl) boost::intrusive_ptr_release(impl); } - -template <class T> -Handle<T>::Handle(const Handle& h) : impl(h.impl) { if(impl) boost::intrusive_ptr_add_ref(impl); } - -template <class T> -Handle<T>& Handle<T>::operator=(const Handle<T>& h) { Handle<T>(h).swap(*this); return *this; } - -template <class T> -void Handle<T>::swap(Handle<T>& h) { std::swap(impl, h.impl); } - - -/** Access to private impl of a Handle */ -template <class T> -class HandlePrivate { - public: - static boost::intrusive_ptr<T> get(const Handle<T>& h) { return boost::intrusive_ptr<T>(h.impl); } - static void set(Handle<T>& h, const boost::intrusive_ptr<T>& p) { Handle<T>(p.get()).swap(h); } -}; - -template<class T> boost::intrusive_ptr<T> handleGetPtr(Handle<T>& h) { return HandlePrivate<T>::get(h); } -template<class T> boost::intrusive_ptr<const T> handleGetPtr(const Handle<T>& h) { return HandlePrivate<T>::get(h); } -template<class T> void handleSetPtr(Handle<T>& h, const boost::intrusive_ptr<T>& p) { HandlePrivate<T>::set(h, p); } - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_HANDLEPRIVATE_H*/ diff --git a/cpp/src/qpid/client/LocalQueue.cpp b/cpp/src/qpid/client/LocalQueue.cpp index 02fecf804f..dfd8405a7f 100644 --- a/cpp/src/qpid/client/LocalQueue.cpp +++ b/cpp/src/qpid/client/LocalQueue.cpp @@ -24,7 +24,7 @@ #include "qpid/framing/FrameSet.h" #include "qpid/framing/MessageTransferBody.h" #include "qpid/framing/reply_exceptions.h" -#include "HandlePrivate.h" +#include "PrivateImplRef.h" #include "SubscriptionImpl.h" #include "CompletionImpl.h" @@ -52,8 +52,9 @@ bool LocalQueue::get(Message& result, sys::Duration timeout) { bool ok = queue->pop(content, timeout); if (!ok) return false; if (content->isA<MessageTransferBody>()) { - result = Message(new MessageImpl(*content)); - boost::intrusive_ptr<SubscriptionImpl> si = HandlePrivate<SubscriptionImpl>::get(subscription); + + *MessageImpl::get(result) = MessageImpl(*content); + boost::intrusive_ptr<SubscriptionImpl> si = PrivateImplRef<Subscription>::get(subscription); assert(si); if (si) si->received(result); return true; diff --git a/cpp/src/qpid/client/Message.cpp b/cpp/src/qpid/client/Message.cpp index 962ce26305..501f7e7cd8 100644 --- a/cpp/src/qpid/client/Message.cpp +++ b/cpp/src/qpid/client/Message.cpp @@ -20,17 +20,23 @@ */ #include "Message.h" -#include "PrivateImplPrivate.h" #include "MessageImpl.h" namespace qpid { namespace client { -template class PrivateImpl<MessageImpl>; +Message::Message(MessageImpl* mi) : impl(mi) {} -Message::Message(const std::string& data, const std::string& routingKey) : PrivateImpl<MessageImpl>(new MessageImpl(data, routingKey)) {} -Message::Message(MessageImpl* i) : PrivateImpl<MessageImpl>(i) {} -Message::~Message() {} +Message::Message(const std::string& data, const std::string& routingKey) + : impl(new MessageImpl(data, routingKey)) {} + +Message::Message(const Message& m) : impl(new MessageImpl(*m.impl)) {} + +Message::~Message() { delete impl; } + +Message& Message::operator=(const Message& m) { *impl = *m.impl; return *this; } + +void Message::swap(Message& m) { std::swap(impl, m.impl); } std::string Message::getDestination() const { return impl->getDestination(); } bool Message::isRedelivered() const { return impl->isRedelivered(); } diff --git a/cpp/src/qpid/client/Message.h b/cpp/src/qpid/client/Message.h index 97238db647..3a6f1814cd 100644 --- a/cpp/src/qpid/client/Message.h +++ b/cpp/src/qpid/client/Message.h @@ -22,7 +22,6 @@ * */ -#include "qpid/client/PrivateImpl.h" #include "qpid/client/ClientImportExport.h" #include "qpid/framing/MessageProperties.h" #include "qpid/framing/DeliveryProperties.h" @@ -113,17 +112,21 @@ class MessageImpl; * * */ -class Message : public PrivateImpl<MessageImpl> +class Message { public: /** Create a Message. *@param data Data for the message body. *@param routingKey Passed to the exchange that routes the message. */ - QPID_CLIENT_EXTERN Message(const std::string& data=std::string(), - const std::string& routingKey=std::string()); - + QPID_CLIENT_EXTERN Message( + const std::string& data=std::string(), + const std::string& routingKey=std::string()); + Message(MessageImpl*); ///< @internal + QPID_CLIENT_EXTERN Message(const Message&); QPID_CLIENT_EXTERN ~Message(); + QPID_CLIENT_EXTERN Message& operator=(const Message&); + QPID_CLIENT_EXTERN void swap(Message&); QPID_CLIENT_EXTERN void setData(const std::string&); QPID_CLIENT_EXTERN const std::string& getData() const; @@ -162,8 +165,9 @@ public: ///@internal QPID_CLIENT_EXTERN const framing::SequenceNumber& getId() const; - ///@internal - Message(MessageImpl*); + private: + MessageImpl* impl; + friend class MessageImpl; // Helper template for implementation }; }} diff --git a/cpp/src/qpid/client/MessageImpl.h b/cpp/src/qpid/client/MessageImpl.h index c06d9b5afc..8a529a4dde 100644 --- a/cpp/src/qpid/client/MessageImpl.h +++ b/cpp/src/qpid/client/MessageImpl.h @@ -21,10 +21,11 @@ * under the License. * */ -#include <string> +#include "Message.h" #include "qpid/client/Session.h" #include "qpid/framing/MessageTransferBody.h" #include "qpid/framing/TransferContent.h" +#include <string> namespace qpid { namespace client { @@ -64,6 +65,9 @@ public: /**@internal for incoming messages */ MessageImpl(const framing::FrameSet& frameset); + + static MessageImpl* get(Message& m) { return m.impl; } + static const MessageImpl* get(const Message& m) { return m.impl; } private: //method and id are only set for received messages: diff --git a/cpp/src/qpid/client/PrivateImpl.h b/cpp/src/qpid/client/PrivateImpl.h deleted file mode 100644 index 6e5ea35ce0..0000000000 --- a/cpp/src/qpid/client/PrivateImpl.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef QPID_CLIENT_PRIVATEIMPL_H -#define QPID_CLIENT_PRIVATEIMPL_H - -/* - * - * 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 "qpid/client/ClientImportExport.h" - -namespace qpid { -namespace client { - -template <class T> class PrivateImplPrivate; - -/** - * Base classes for objects with a private implementation. - * - * PrivateImpl objects have value semantics: copying the object also - * makes a copy of the implementation. - */ -template <class T> class PrivateImpl { - public: - QPID_CLIENT_EXTERN ~PrivateImpl(); - QPID_CLIENT_EXTERN PrivateImpl(const PrivateImpl&); - QPID_CLIENT_EXTERN PrivateImpl& operator=(const PrivateImpl&); - QPID_CLIENT_EXTERN void swap(PrivateImpl<T>&); - - protected: - QPID_CLIENT_EXTERN PrivateImpl(T*); - T* impl; - - friend class PrivateImplPrivate<T>; -}; - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_PRIVATEIMPL_H*/ diff --git a/cpp/src/qpid/client/PrivateImplPrivate.h b/cpp/src/qpid/client/PrivateImplPrivate.h deleted file mode 100644 index 021456e085..0000000000 --- a/cpp/src/qpid/client/PrivateImplPrivate.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef QPID_CLIENT_PRIVATEIMPLPRIVATE_H -#define QPID_CLIENT_PRIVATEIMPLPRIVATE_H - -/* - * - * 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 <algorithm> - -namespace qpid { -namespace client { - -/** @file - * Implementation of PrivateImpl functions, to include in .cpp file of handle subclasses. - * T can be any class with value semantics. - */ - -template <class T> -PrivateImpl<T>::PrivateImpl(T* p) : impl(p) { assert(impl); } - -template <class T> -PrivateImpl<T>::~PrivateImpl() { delete impl; } - -template <class T> -PrivateImpl<T>::PrivateImpl(const PrivateImpl& h) : impl(new T(*h.impl)) {} - -template <class T> -PrivateImpl<T>& PrivateImpl<T>::operator=(const PrivateImpl<T>& h) { PrivateImpl<T>(h).swap(*this); return *this; } - -template <class T> -void PrivateImpl<T>::swap(PrivateImpl<T>& h) { std::swap(impl, h.impl); } - - -/** Access to private impl of a PrivateImpl */ -template <class T> -class PrivateImplPrivate { - public: - static T* get(const PrivateImpl<T>& h) { return h.impl; } - static void set(PrivateImpl<T>& h, const T& p) { PrivateImpl<T>(p).swap(h); } -}; - -template<class T> T* privateImplGetPtr(PrivateImpl<T>& h) { return PrivateImplPrivate<T>::get(h); } -template<class T> T* privateImplGetPtr(const PrivateImpl<T>& h) { return PrivateImplPrivate<T>::get(h); } -template<class T> void privateImplSetPtr(PrivateImpl<T>& h, const T*& p) { PrivateImplPrivate<T>::set(h, p); } - -}} // namespace qpid::client - -#endif /*!QPID_CLIENT_PRIVATEIMPLPRIVATE_H*/ - diff --git a/cpp/src/qpid/client/PrivateImplRef.h b/cpp/src/qpid/client/PrivateImplRef.h new file mode 100644 index 0000000000..ae29318eb9 --- /dev/null +++ b/cpp/src/qpid/client/PrivateImplRef.h @@ -0,0 +1,93 @@ +#ifndef QPID_CLIENT_PRIVATEIMPL_H +#define QPID_CLIENT_PRIVATEIMPL_H + +/* + * + * 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 "qpid/client/ClientImportExport.h" +#include <boost/intrusive_ptr.hpp> +#include "qpid/RefCounted.h" + +namespace qpid { +namespace client { + +// FIXME aconway 2009-04-24: details! +/** @file + * + * Helper class to implement a class with a private, reference counted + * implementation and reference semantics. + * + * Such classes are used in the public API to hide implementation, they + * should. Example of use: + * + * === Foo.h + * + * template <class T> PrivateImplRef; + * class FooImpl; + * + * Foo : public Handle<FooImpl> { + * public: + * Foo(FooImpl* = 0); + * Foo(const Foo&); + * ~Foo(); + * Foo& operator=(const Foo&); + * + * int fooDo(); // and other Foo functions... + * + * private: + * typedef FooImpl Impl; + * Impl* impl; + * friend class PrivateImplRef<Foo>; + * + * === Foo.cpp + * + * typedef PrivateImplRef<Foo> PI; + * Foo::Foo(FooImpl* p) { PI::ctor(*this, p); } + * Foo::Foo(const Foo& c) : Handle<FooImpl>() { PI::copy(*this, c); } + * Foo::~Foo() { PI::dtor(*this); } + * Foo& Foo::operator=(const Foo& c) { return PI::assign(*this, c); } + * + * int foo::fooDo() { return impl->fooDo(); } + * + */ +template <class T> class PrivateImplRef { + public: + typedef typename T::Impl Impl; + typedef boost::intrusive_ptr<Impl> intrusive_ptr; + + static intrusive_ptr get(const T& t) { return intrusive_ptr(t.impl); } + + static void set(T& t, const intrusive_ptr& p) { + if(t.impl) boost::intrusive_ptr_release(t.impl); + t.impl = p.get(); + if (t.impl) boost::intrusive_ptr_add_ref(t.impl); + } + + // Helper functions to implement the ctor, dtor, copy, assign + static void ctor(T& t, Impl* p) { t.impl = p; if (p) boost::intrusive_ptr_add_ref(p); } + static void copy(T& t, const T& x) { t.impl = 0; assign(t, x); } + static void dtor(T& t) { if(t.impl) boost::intrusive_ptr_release(t.impl); } + static T& assign(T& t, const T& x) { set(t, get(x)); return t;} +}; + +}} // namespace qpid::client + +#endif /*!QPID_CLIENT_PRIVATEIMPL_H*/ diff --git a/cpp/src/qpid/client/Subscription.cpp b/cpp/src/qpid/client/Subscription.cpp index 37f5557d51..285a8f242f 100644 --- a/cpp/src/qpid/client/Subscription.cpp +++ b/cpp/src/qpid/client/Subscription.cpp @@ -22,13 +22,17 @@ #include "Subscription.h" #include "SubscriptionImpl.h" #include "CompletionImpl.h" -#include "HandlePrivate.h" +#include "PrivateImplRef.h" #include "qpid/framing/enum.h" namespace qpid { namespace client { -template class Handle<SubscriptionImpl>; +typedef PrivateImplRef<Subscription> PI; +Subscription::Subscription(SubscriptionImpl* p) { PI::ctor(*this, p); } +Subscription::~Subscription() { PI::dtor(*this); } +Subscription::Subscription(const Subscription& c) : Handle<SubscriptionImpl>() { PI::copy(*this, c); } +Subscription& Subscription::operator=(const Subscription& c) { return PI::assign(*this, c); } std::string Subscription::getName() const { return impl->getName(); } diff --git a/cpp/src/qpid/client/Subscription.h b/cpp/src/qpid/client/Subscription.h index 43c6100254..f39cdd50ac 100644 --- a/cpp/src/qpid/client/Subscription.h +++ b/cpp/src/qpid/client/Subscription.h @@ -22,15 +22,16 @@ * */ +#include "qpid/client/Handle.h" #include "qpid/client/Session.h" #include "qpid/client/SubscriptionSettings.h" -#include "qpid/client/Handle.h" #include "qpid/client/Message.h" #include "qpid/client/ClientImportExport.h" namespace qpid { namespace client { +template <class> class PrivateImplRef; class SubscriptionImpl; class SubscriptionManager; @@ -40,7 +41,11 @@ class SubscriptionManager; */ class Subscription : public Handle<SubscriptionImpl> { public: - QPID_CLIENT_EXTERN Subscription(SubscriptionImpl* si=0) : Handle<SubscriptionImpl>(si) {} + QPID_CLIENT_EXTERN Subscription(SubscriptionImpl* = 0); + QPID_CLIENT_EXTERN Subscription(const Subscription&); + QPID_CLIENT_EXTERN ~Subscription(); + QPID_CLIENT_EXTERN Subscription& operator=(const Subscription&); + /** The name of the subscription, used as the "destination" for messages from the broker. * Usually the same as the queue name but can be set differently. @@ -109,6 +114,8 @@ class Subscription : public Handle<SubscriptionImpl> { /** Grant the specified amount of byte credit */ QPID_CLIENT_EXTERN void grantByteCredit(uint32_t); + private: + friend class PrivateImplRef<Subscription>; friend class SubscriptionManager; }; }} // namespace qpid::client diff --git a/cpp/src/qpid/client/SubscriptionImpl.cpp b/cpp/src/qpid/client/SubscriptionImpl.cpp index 82c920cf47..69f79a1436 100644 --- a/cpp/src/qpid/client/SubscriptionImpl.cpp +++ b/cpp/src/qpid/client/SubscriptionImpl.cpp @@ -24,8 +24,6 @@ #include "CompletionImpl.h" #include "SubscriptionManager.h" #include "SubscriptionSettings.h" -#include "HandlePrivate.h" -#include "PrivateImplPrivate.h" namespace qpid { namespace client { @@ -118,9 +116,10 @@ void SubscriptionImpl::cancel() { manager.cancel(name); } void SubscriptionImpl::received(Message& m) { Mutex::ScopedLock l(lock); - if (privateImplGetPtr(m)->getMethod().getAcquireMode() == ACQUIRE_MODE_NOT_ACQUIRED) + MessageImpl& mi = *MessageImpl::get(m); + if (mi.getMethod().getAcquireMode() == ACQUIRE_MODE_NOT_ACQUIRED) unacquired.add(m.getId()); - else if (privateImplGetPtr(m)->getMethod().getAcceptMode() == ACCEPT_MODE_EXPLICIT) + else if (mi.getMethod().getAcceptMode() == ACCEPT_MODE_EXPLICIT) unaccepted.add(m.getId()); if (listener) { diff --git a/cpp/src/qpid/client/TypedResult.h b/cpp/src/qpid/client/TypedResult.h index 2e54f9fdfc..bc4b65d23e 100644 --- a/cpp/src/qpid/client/TypedResult.h +++ b/cpp/src/qpid/client/TypedResult.h @@ -40,7 +40,7 @@ template <class T> class TypedResult : public Completion public: ///@internal - TypedResult(CompletionImpl* c) : Completion(c), decoded(false) {} + TypedResult(const Completion& c) : Completion(c), decoded(false) {} /** * Wait for the asynchronous command that returned this TypedResult to complete |
