summaryrefslogtreecommitdiff
path: root/cpp/src
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2009-05-01 14:53:05 +0000
committerAlan Conway <aconway@apache.org>2009-05-01 14:53:05 +0000
commitdd79366789a749856de0e41633146340c2b79f9a (patch)
tree69e792e992a3071a19c112d6bd9d715f4ce1d27e /cpp/src
parentdb687f6ce97fe987936711f9c46966d45cf24834 (diff)
downloadqpid-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.am4
-rw-r--r--cpp/src/qpid/client/Completion.cpp12
-rw-r--r--cpp/src/qpid/client/Completion.h22
-rw-r--r--cpp/src/qpid/client/Handle.h23
-rw-r--r--cpp/src/qpid/client/HandleAccess.h41
-rw-r--r--cpp/src/qpid/client/HandlePrivate.h67
-rw-r--r--cpp/src/qpid/client/LocalQueue.cpp7
-rw-r--r--cpp/src/qpid/client/Message.cpp16
-rw-r--r--cpp/src/qpid/client/Message.h18
-rw-r--r--cpp/src/qpid/client/MessageImpl.h6
-rw-r--r--cpp/src/qpid/client/PrivateImpl.h54
-rw-r--r--cpp/src/qpid/client/PrivateImplPrivate.h66
-rw-r--r--cpp/src/qpid/client/PrivateImplRef.h93
-rw-r--r--cpp/src/qpid/client/Subscription.cpp8
-rw-r--r--cpp/src/qpid/client/Subscription.h11
-rw-r--r--cpp/src/qpid/client/SubscriptionImpl.cpp7
-rw-r--r--cpp/src/qpid/client/TypedResult.h2
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