You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by sh...@apache.org on 2008/10/03 20:46:00 UTC

svn commit: r701486 - in /incubator/qpid/trunk/qpid/cpp/src/qpid/sys: Condition.h Monitor.h Mutex.h Thread.h windows/Condition.h windows/Mutex.h windows/Thread.cpp windows/check.h

Author: shuston
Date: Fri Oct  3 11:46:00 2008
New Revision: 701486

URL: http://svn.apache.org/viewvc?rev=701486&view=rev
Log:
Add Windows threading and synchronization primitives

Added:
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp   (with props)
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h   (with props)
Modified:
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Condition.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Monitor.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Mutex.h
    incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Thread.h

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Condition.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Condition.h?rev=701486&r1=701485&r2=701486&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Condition.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Condition.h Fri Oct  3 11:46:00 2008
@@ -24,6 +24,8 @@
 
 #ifdef USE_APR_PLATFORM
 #include "apr/Condition.h"
+#elif defined (_WIN32)
+#include "windows/Condition.h"
 #else
 #include "posix/Condition.h"
 #endif

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Monitor.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Monitor.h?rev=701486&r1=701485&r2=701486&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Monitor.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Monitor.h Fri Oct  3 11:46:00 2008
@@ -22,7 +22,6 @@
  *
  */
 
-#include <sys/errno.h>
 #include "Condition.h"
 
 namespace qpid {
@@ -33,7 +32,6 @@
  */
 class Monitor : public Mutex, public Condition {
   public:
-    using Condition::wait;
     inline void wait();
     inline bool wait(const AbsTime& absoluteTime);
 };

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Mutex.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Mutex.h?rev=701486&r1=701485&r2=701486&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Mutex.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Mutex.h Fri Oct  3 11:46:00 2008
@@ -82,6 +82,8 @@
     
 #ifdef USE_APR_PLATFORM
 #include "apr/Mutex.h"
+#elif defined (_WIN32)
+#include "windows/Mutex.h"
 #else
 #include "posix/Mutex.h"
 #endif

Modified: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Thread.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Thread.h?rev=701486&r1=701485&r2=701486&view=diff
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Thread.h (original)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/Thread.h Fri Oct  3 11:46:00 2008
@@ -23,6 +23,14 @@
  */
 #include <boost/shared_ptr.hpp>
 
+#ifdef _WIN32
+#  define QPID_TSS __declspec(thread)
+#elif defined (gcc)
+#  define QPID_TSS __thread
+#else
+#  define QPID_TSS
+#endif
+
 namespace qpid {
 namespace sys {
 

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h?rev=701486&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h Fri Oct  3 11:46:00 2008
@@ -0,0 +1,82 @@
+#ifndef _sys_windows_Condition_h
+#define _sys_windows_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 "qpid/sys/Mutex.h"
+#include "qpid/sys/Time.h"
+
+#include <time.h>
+#include <boost/noncopyable.hpp>
+#include <boost/thread/condition.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <windows.h>
+
+namespace qpid {
+namespace sys {
+
+// Private Time related implementation details
+void toPtime(boost::posix_time::ptime& pt, const AbsTime& t);
+
+/**
+ * A condition variable for thread synchronization.
+ */
+class Condition : private boost::noncopyable
+{
+  public:
+    inline Condition();
+    inline ~Condition();
+    inline void wait(Mutex&);
+    inline bool wait(Mutex&, const AbsTime& absoluteTime);
+    inline void notify();
+    inline void notifyAll();
+
+  private:
+    boost::condition_variable_any condition;
+};
+
+Condition::Condition() {
+}
+
+Condition::~Condition() {
+}
+
+void Condition::wait(Mutex& mutex) {
+    condition.wait(mutex.mutex);
+}
+
+bool Condition::wait(Mutex& mutex, const AbsTime& absoluteTime){
+    boost::system_time st;
+    toPtime(st, absoluteTime);
+    return condition.timed_wait(mutex.mutex, st);
+}
+
+void Condition::notify(){
+    condition.notify_one();
+}
+
+void Condition::notifyAll(){
+    condition.notify_all();
+}
+
+}}
+#endif  /*!_sys_windows_Condition_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Condition.h
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h?rev=701486&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h Fri Oct  3 11:46:00 2008
@@ -0,0 +1,188 @@
+#ifndef _sys_windows_Mutex_h
+#define _sys_windows_Mutex_h
+
+/*
+ *
+ * Copyright (c) 2008 The Apache Software Foundation
+ *
+ * Licensed 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 "check.h"
+
+#include <boost/version.hpp>
+#if (BOOST_VERSION < 103500)
+#error The Windows port requires Boost version 1.35.0 or later
+#endif
+
+#include <boost/noncopyable.hpp>
+#include <boost/thread/recursive_mutex.hpp>
+#include <boost/thread/shared_mutex.hpp>
+#include <boost/thread/thread_time.hpp>
+#include <boost/thread/tss.hpp>
+
+namespace qpid {
+namespace sys {
+
+class Condition;
+
+/**
+ * Mutex lock.
+ */
+class Mutex : private boost::noncopyable {
+    friend class Condition;
+
+public:
+    typedef ::qpid::sys::ScopedLock<Mutex> ScopedLock;
+    typedef ::qpid::sys::ScopedUnlock<Mutex> ScopedUnlock;
+     
+    inline Mutex();
+    inline ~Mutex();
+    inline void lock();  
+    inline void unlock();
+    inline bool trylock();  
+
+
+protected:
+    boost::recursive_mutex mutex;
+};
+
+/**
+ * RW lock.
+ */
+class RWlock : private boost::noncopyable {
+    friend class Condition;
+
+public:
+    typedef ::qpid::sys::ScopedRlock<RWlock> ScopedRlock;
+    typedef ::qpid::sys::ScopedWlock<RWlock> ScopedWlock;
+    
+    inline RWlock();
+    inline ~RWlock();
+    inline void wlock();  // will write-lock
+    inline void rlock();  // will read-lock
+    inline void unlock();
+    inline void trywlock();  // will write-try
+    inline void tryrlock();  // will read-try
+
+protected:
+    boost::shared_mutex rwMutex;
+    boost::thread_specific_ptr<bool> haveWrite;
+
+    inline bool &write (void);
+};
+
+
+/**
+ * PODMutex is a POD, can be static-initialized with
+ * PODMutex m = QPID_PODMUTEX_INITIALIZER
+ */
+struct PODMutex 
+{
+    typedef ::qpid::sys::ScopedLock<PODMutex> ScopedLock;
+
+    inline void lock();  
+    inline void unlock();
+    inline bool trylock();  
+
+    // Must be public to be a POD:
+    boost::recursive_mutex mutex;
+};
+
+#define QPID_MUTEX_INITIALIZER 0
+
+void PODMutex::lock() {
+    mutex.lock();
+}
+
+void PODMutex::unlock() {
+    mutex.unlock();
+}
+
+bool PODMutex::trylock() {
+    return mutex.try_lock();
+}
+
+Mutex::Mutex() {
+}
+
+Mutex::~Mutex(){
+}
+
+void Mutex::lock() {
+    mutex.lock();
+}
+
+void Mutex::unlock() {
+    mutex.unlock();
+}
+
+bool Mutex::trylock() {
+    return mutex.try_lock();
+}
+
+
+RWlock::RWlock() {
+}
+
+RWlock::~RWlock(){
+}
+
+void RWlock::wlock() {
+    bool &writer = write();
+    rwMutex.lock();
+    writer = true;    // Remember this thread has write lock held.
+}
+
+void RWlock::rlock() {
+    bool &writer = write();
+    rwMutex.lock_shared();
+    writer = false;   // Remember this thread has shared lock held.
+}
+
+void RWlock::unlock() {
+    bool &writer = write();
+    if (writer)
+        rwMutex.unlock();
+    else
+        rwMutex.unlock_shared();
+}
+
+void RWlock::trywlock() {
+    bool &writer = write();
+    // shared_mutex::try_lock() seems to not be available... emulate it with
+    // a timed lock().
+    boost::system_time now = boost::get_system_time();
+    if (rwMutex.timed_lock(now))
+        writer = true;
+}
+
+void RWlock::tryrlock() {
+    bool &writer = write();
+    if (rwMutex.try_lock_shared())
+        writer = false;
+}
+
+bool & RWlock::write (void) {
+    // Accessing thread-specific and stack-local info, so no locks needed.
+    bool *writePtr = haveWrite.get();
+    if (writePtr == 0) {
+        writePtr = new bool(false);
+        haveWrite.reset(writePtr);
+    }
+    return *writePtr;
+}
+
+}}
+#endif  /*!_sys_windows_Mutex_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Mutex.h
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp?rev=701486&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp Fri Oct  3 11:46:00 2008
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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/sys/Thread.h"
+#include "qpid/sys/Runnable.h"
+#include "check.h"
+
+#include <process.h>
+#include <windows.h>
+
+namespace {
+unsigned __stdcall runRunnable(void* p)
+{
+    static_cast<qpid::sys::Runnable*>(p)->run();
+    _endthreadex(0);
+    return 0;
+}
+}
+
+namespace qpid {
+namespace sys {
+
+class ThreadPrivate {
+    friend class Thread;
+
+    HANDLE threadHandle;
+    unsigned threadId;
+    
+    ThreadPrivate(Runnable* runnable) {
+        uintptr_t h =  _beginthreadex(0,
+                                      0,
+                                      runRunnable,
+                                      runnable,
+                                      0,
+                                      &threadId);
+        QPID_WINDOWS_CHECK_CRT_NZ(h);
+        threadHandle = reinterpret_cast<HANDLE>(h);
+    }
+    
+    ThreadPrivate()
+      : threadHandle(GetCurrentThread()), threadId(GetCurrentThreadId()) {}
+};
+
+Thread::Thread() {}
+
+Thread::Thread(Runnable* runnable) : impl(new ThreadPrivate(runnable)) {}
+
+Thread::Thread(Runnable& runnable) : impl(new ThreadPrivate(&runnable)) {}
+
+void Thread::join() {
+    if (impl) {
+        DWORD status = WaitForSingleObject (impl->threadHandle, INFINITE);
+        QPID_WINDOWS_CHECK_NOT(status, WAIT_FAILED);
+        CloseHandle (impl->threadHandle);
+        impl->threadHandle = 0;
+    }
+}
+
+unsigned long Thread::id() {
+    return impl ? impl->threadId : 0;
+}
+
+/* static */
+Thread Thread::current() {
+    Thread t;
+    t.impl.reset(new ThreadPrivate());
+    return t;
+}
+
+}}  /* qpid::sys */

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/Thread.cpp
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h
URL: http://svn.apache.org/viewvc/incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h?rev=701486&view=auto
==============================================================================
--- incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h (added)
+++ incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h Fri Oct  3 11:46:00 2008
@@ -0,0 +1,48 @@
+#ifndef _windows_check_h
+#define _windows_check_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/Exception.h"
+#include "qpid/sys/StrError.h"
+
+#define QPID_WINDOWS_ERROR(ERRVAL) qpid::Exception(QPID_MSG(qpid::sys::strError(ERRVAL)))
+#define QPID_WINDOWS_CRT_ERROR(ERRNO) qpid::Exception(QPID_MSG(qpid::sys::strError(ERRNO)))
+
+/** THROW QPID_WINDOWS_ERROR(::GetLastError()) if RESULT is NULL */
+#define QPID_WINDOWS_CHECK_NULL(RESULT)                        \
+    if ((RESULT) == NULL) throw QPID_WINDOWS_ERROR((::GetLastError()))
+
+#define QPID_WINDOWS_CHECK_NOT(RESULT,VAL)                                 \
+  if ((RESULT) == (VAL)) throw QPID_WINDOWS_ERROR((::GetLastError()))
+
+#define QPID_WINDOWS_CHECK_ASYNC_START(STATUS)                 \
+    if (!(STATUS) && ::WSAGetLastError() != ERROR_IO_PENDING)  \
+        throw QPID_WINDOWS_ERROR((::WSAGetLastError()))
+
+#define QPID_WINDOWS_CHECK_CRT_NZ(VAL)   \
+    if ((VAL) == 0) throw QPID_WINDOWS_CRT_ERROR(errno)
+
+#define QPID_WINSOCK_CHECK(OP)                        \
+    if ((OP) == SOCKET_ERROR) throw QPID_WINDOWS_ERROR((::WSAGetLastError()))
+
+#endif  /*!_windows_check_h*/

Propchange: incubator/qpid/trunk/qpid/cpp/src/qpid/sys/windows/check.h
------------------------------------------------------------------------------
    svn:executable = *