summaryrefslogtreecommitdiff
path: root/cpp/lib/common/sys
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2007-02-21 19:25:45 +0000
committerAlan Conway <aconway@apache.org>2007-02-21 19:25:45 +0000
commit876d0b94c37f252b08c81656386100fad18a8a46 (patch)
tree4840b0d697d4629fd5c518507b58fceb7de1578a /cpp/lib/common/sys
parentc36fb4454be5ce4311aa5f5d0e5683db713c5545 (diff)
downloadqpid-python-876d0b94c37f252b08c81656386100fad18a8a46.tar.gz
Thread safety fixes for race conditions on incoming messages.
* cpp/lib/client/MessageListener.h: const correctness. * cpp/tests/*: MessageListener const change. * cpp/lib/broker/Content.h: Removed out-of-date FIXME comments. * cpp/lib/client/ClientChannel.h/ .cpp(): - added locking for consumers map and other member access. - refactored implementations of Basic get, deliver, return: most logic now encapsulted in IncomingMessage class. - fix channel close problems. * cpp/lib/client/ClientMessage.h/.cpp: - const correctness & API convenience fixes. - getMethod/setMethod/getHeader: for new IncomingMessage * cpp/lib/client/Connection.h/.cpp: - Fixes to channel closure. * cpp/lib/client/IncomingMessage.h/.cpp: - Encapsulate *all* incoming message handling for client. - Moved handling of BasicGetOk to IncomingMessage to fix race. - Thread safety fixes. * cpp/lib/client/ResponseHandler.h/.cpp: - added getResponse for ClientChannel. * cpp/lib/common/Exception.h: - added missing throwSelf implementations. - added ShutdownException as general purpose shut-down indicator. - added EmptyException as general purpose "empty" indicator. * cpp/lib/common/sys/Condition|Monitor|Mutex.h|.cpp: - Condition variable abstraction extracted from Monitor for situations where a single lock is associated with multiple conditions. * cpp/tests/ClientChannelTest.cpp: - Test incoming message transfer, get, consume etc. git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/qpid.0-9@510161 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/lib/common/sys')
-rw-r--r--cpp/lib/common/sys/Condition.h128
-rw-r--r--cpp/lib/common/sys/Monitor.h84
-rw-r--r--cpp/lib/common/sys/Mutex.h3
3 files changed, 137 insertions, 78 deletions
diff --git a/cpp/lib/common/sys/Condition.h b/cpp/lib/common/sys/Condition.h
new file mode 100644
index 0000000000..9d70af5b84
--- /dev/null
+++ b/cpp/lib/common/sys/Condition.h
@@ -0,0 +1,128 @@
+#ifndef _sys_Condition_h
+#define _sys_Condition_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 <sys/errno.h>
+#include <boost/noncopyable.hpp>
+#include <sys/Mutex.h>
+#include <sys/Time.h>
+
+#ifdef USE_APR
+# include <apr_thread_cond.h>
+#endif
+
+namespace qpid {
+namespace sys {
+
+/**
+ * A condition variable for thread synchronization.
+ */
+class Condition
+{
+ public:
+ inline Condition();
+ inline ~Condition();
+ inline void wait(Mutex&);
+ inline bool wait(Mutex&, const Time& absoluteTime);
+ inline void notify();
+ inline void notifyAll();
+
+ private:
+#ifdef USE_APR
+ apr_thread_cond_t* condition;
+#else
+ pthread_cond_t condition;
+#endif
+};
+
+
+// APR ================================================================
+#ifdef USE_APR
+
+Condition::Condition() {
+ CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get()));
+}
+
+Condition::~Condition() {
+ CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition));
+}
+
+void Condition::wait(Mutex& mutex) {
+ CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex.mutex));
+}
+
+bool Condition::wait(Mutex& mutex, const Time& absoluteTime){
+ // APR uses microseconds.
+ apr_status_t status =
+ apr_thread_cond_timedwait(
+ condition, mutex.mutex, absoluteTime/TIME_USEC);
+ if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status);
+ return status == 0;
+}
+
+void Condition::notify(){
+ CHECK_APR_SUCCESS(apr_thread_cond_signal(condition));
+}
+
+void Condition::notifyAll(){
+ CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition));
+}
+
+#else
+// POSIX ================================================================
+
+Condition::Condition() {
+ QPID_POSIX_THROW_IF(pthread_cond_init(&condition, 0));
+}
+
+Condition::~Condition() {
+ QPID_POSIX_THROW_IF(pthread_cond_destroy(&condition));
+}
+
+void Condition::wait(Mutex& mutex) {
+ QPID_POSIX_THROW_IF(pthread_cond_wait(&condition, &mutex.mutex));
+}
+
+bool Condition::wait(Mutex& mutex, const Time& absoluteTime){
+ struct timespec ts;
+ toTimespec(ts, absoluteTime);
+ int status = pthread_cond_timedwait(&condition, &mutex.mutex, &ts);
+ if (status != 0) {
+ if (status == ETIMEDOUT) return false;
+ throw QPID_POSIX_ERROR(status);
+ }
+ return true;
+}
+
+void Condition::notify(){
+ QPID_POSIX_THROW_IF(pthread_cond_signal(&condition));
+}
+
+void Condition::notifyAll(){
+ QPID_POSIX_THROW_IF(pthread_cond_broadcast(&condition));
+}
+#endif /*USE_APR*/
+
+
+}}
+#endif /*!_sys_Condition_h*/
diff --git a/cpp/lib/common/sys/Monitor.h b/cpp/lib/common/sys/Monitor.h
index e58931e699..a3bbd3c5aa 100644
--- a/cpp/lib/common/sys/Monitor.h
+++ b/cpp/lib/common/sys/Monitor.h
@@ -23,9 +23,7 @@
*/
#include <sys/errno.h>
-#include <boost/noncopyable.hpp>
-#include <sys/Mutex.h>
-#include <sys/Time.h>
+#include <sys/Condition.h>
#ifdef USE_APR
# include <apr_thread_cond.h>
@@ -37,91 +35,21 @@ namespace sys {
/**
* A monitor is a condition variable and a mutex
*/
-class Monitor : public Mutex
-{
+class Monitor : public Mutex, public Condition {
public:
- inline Monitor();
- inline ~Monitor();
+ using Condition::wait;
inline void wait();
inline bool wait(const Time& absoluteTime);
- inline void notify();
- inline void notifyAll();
-
- private:
-#ifdef USE_APR
- apr_thread_cond_t* condition;
-#else
- pthread_cond_t condition;
-#endif
};
-// APR ================================================================
-#ifdef USE_APR
-
-Monitor::Monitor() {
- CHECK_APR_SUCCESS(apr_thread_cond_create(&condition, APRPool::get()));
-}
-
-Monitor::~Monitor() {
- CHECK_APR_SUCCESS(apr_thread_cond_destroy(condition));
-}
-
-void Monitor::wait() {
- CHECK_APR_SUCCESS(apr_thread_cond_wait(condition, mutex));
-}
-
-bool Monitor::wait(const Time& absoluteTime){
- // APR uses microseconds.
- apr_status_t status =
- apr_thread_cond_timedwait(condition, mutex, absoluteTime/TIME_USEC);
- if(status != APR_TIMEUP) CHECK_APR_SUCCESS(status);
- return status == 0;
-}
-
-void Monitor::notify(){
- CHECK_APR_SUCCESS(apr_thread_cond_signal(condition));
-}
-
-void Monitor::notifyAll(){
- CHECK_APR_SUCCESS(apr_thread_cond_broadcast(condition));
-}
-
-#else
-// POSIX ================================================================
-
-Monitor::Monitor() {
- QPID_POSIX_THROW_IF(pthread_cond_init(&condition, 0));
-}
-
-Monitor::~Monitor() {
- QPID_POSIX_THROW_IF(pthread_cond_destroy(&condition));
-}
-
void Monitor::wait() {
- QPID_POSIX_THROW_IF(pthread_cond_wait(&condition, &mutex));
-}
-
-bool Monitor::wait(const Time& absoluteTime){
- struct timespec ts;
- toTimespec(ts, absoluteTime);
- int status = pthread_cond_timedwait(&condition, &mutex, &ts);
- if (status != 0) {
- if (status == ETIMEDOUT) return false;
- throw QPID_POSIX_ERROR(status);
- }
- return true;
+ Condition::wait(*this);
}
-void Monitor::notify(){
- QPID_POSIX_THROW_IF(pthread_cond_signal(&condition));
+bool Monitor::wait(const Time& absoluteTime) {
+ return Condition::wait(*this, absoluteTime);
}
-void Monitor::notifyAll(){
- QPID_POSIX_THROW_IF(pthread_cond_broadcast(&condition));
-}
-#endif /*USE_APR*/
-
-
}}
#endif /*!_sys_Monitor_h*/
diff --git a/cpp/lib/common/sys/Mutex.h b/cpp/lib/common/sys/Mutex.h
index 87d537fb9e..9db9be0981 100644
--- a/cpp/lib/common/sys/Mutex.h
+++ b/cpp/lib/common/sys/Mutex.h
@@ -32,6 +32,8 @@
namespace qpid {
namespace sys {
+class Condition;
+
/**
* Scoped lock template: calls lock() in ctor, unlock() in dtor.
* L can be any class with lock() and unlock() functions.
@@ -76,6 +78,7 @@ class Mutex : private boost::noncopyable {
#else
pthread_mutex_t mutex;
#endif
+ friend class Condition;
};
#ifdef USE_APR