- Added a mutex and mutex (scoped) lock implementation
authorMarius Tomaschewski <mt@suse.de>
Tue, 31 Jan 2006 16:09:48 +0000 (16:09 +0000)
committerMarius Tomaschewski <mt@suse.de>
Tue, 31 Jan 2006 16:09:48 +0000 (16:09 +0000)
zypp/thread/Makefile.am [new file with mode: 0644]
zypp/thread/Mutex.cc [new file with mode: 0644]
zypp/thread/Mutex.h [new file with mode: 0644]
zypp/thread/MutexException.h [new file with mode: 0644]
zypp/thread/MutexLock.h [new file with mode: 0644]

diff --git a/zypp/thread/Makefile.am b/zypp/thread/Makefile.am
new file mode 100644 (file)
index 0000000..9309ef4
--- /dev/null
@@ -0,0 +1,24 @@
+## Process this file with automake to produce Makefile.in
+## ##################################################
+
+#INCLUDES
+
+## ##################################################
+
+threadincludedir = $(pkgincludedir)/thread
+
+threadinclude_HEADERS =        \
+       MutexException.h        \
+       Mutex.h                 \
+       MutexLock.h
+
+noinst_LTLIBRARIES =   lib@PACKAGE@_thread.la
+
+## ##################################################
+
+lib@PACKAGE@_thread_la_SOURCES =\
+       Mutex.cc
+
+lib@PACKAGE@_thread_la_LDFLAGS = -pthread
+
+## ##################################################
diff --git a/zypp/thread/Mutex.cc b/zypp/thread/Mutex.cc
new file mode 100644 (file)
index 0000000..c9c0560
--- /dev/null
@@ -0,0 +1,107 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/thread/Mutex.cc
+ */
+#include <zypp/thread/Mutex.h>
+#include <zypp/thread/MutexException.h>
+
+
+//////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ////////////////////////////////////////////////////////////////////
+
+  ////////////////////////////////////////////////////////////////////
+  namespace thread
+  { //////////////////////////////////////////////////////////////////
+
+    // -------------------------------------------------------------
+    Mutex::Mutex()
+    {
+      pthread_mutexattr_t attr;
+
+      int ret = pthread_mutexattr_init(&attr);
+      if( ret != 0)
+      {
+        ZYPP_THROW_ERRNO_MSG(zypp::thread::MutexException,
+        "Can't initialize mutex attributes");
+      }
+
+      ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+      if( ret != 0)
+      {
+        ZYPP_THROW_ERRNO_MSG(MutexException,
+        "Can't set recursive mutex attribute");
+      }
+
+      ret = pthread_mutex_init(&m_mutex, &attr);
+      if( ret != 0)
+      {
+        ZYPP_THROW_ERRNO_MSG(MutexException,
+        "Can't initialize recursive mutex");
+      }
+    }
+
+    // -------------------------------------------------------------
+    Mutex::~Mutex()
+    {
+      if( pthread_mutex_destroy(&m_mutex) != 0 && errno == EBUSY)
+      {
+        // try to unlock and to destroy again...
+        if( pthread_mutex_unlock(&m_mutex) == 0)
+        {
+            pthread_mutex_destroy(&m_mutex);
+        }
+        /*
+        else
+        {
+          ZYPP_THROW_ERRNO_MSG(MutexException,
+          "Can't destroy mutex owned by another thread");
+        }
+        */
+      }
+    }
+    // -------------------------------------------------------------
+    void Mutex::lock()
+    {
+      if( pthread_mutex_lock(&m_mutex) != 0)
+      {
+        ZYPP_THROW_ERRNO_MSG(MutexException,
+        "Can't acquire the mutex lock");
+      }
+    }
+
+    // -------------------------------------------------------------
+    void Mutex::unlock()
+    {
+      if( pthread_mutex_unlock(&m_mutex) != 0)
+      {
+        ZYPP_THROW_ERRNO_MSG(MutexException,
+        "Can't release the mutex lock");
+      }
+    }
+
+    // -------------------------------------------------------------
+    bool Mutex::trylock()
+    {
+      return (pthread_mutex_trylock(&m_mutex) == 0);
+    }
+
+
+    //////////////////////////////////////////////////////////////////
+  } // namespace thread
+  ////////////////////////////////////////////////////////////////////
+
+  ////////////////////////////////////////////////////////////////////
+} // namespace zypp
+//////////////////////////////////////////////////////////////////////
+
+/*
+** vim: set ts=2 sts=2 sw=2 ai et:
+*/
diff --git a/zypp/thread/Mutex.h b/zypp/thread/Mutex.h
new file mode 100644 (file)
index 0000000..794b516
--- /dev/null
@@ -0,0 +1,96 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/thread/Mutex.h
+ */
+#ifndef   ZYPP_THREAD_MUTEX_H
+#define   ZYPP_THREAD_MUTEX_H
+
+#include <zypp/base/NonCopyable.h>
+#include <zypp/thread/MutexException.h>
+#include <pthread.h>
+
+//////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  namespace thread
+  { //////////////////////////////////////////////////////////////////
+
+
+    typedef pthread_mutex_t RecursiveMutex_t;
+
+
+    ////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : Mutex
+    //
+    /** A recursive Mutex.
+     */
+    class Mutex: public zypp::base::NonCopyable
+    {
+    public:
+      /** Create a new recursive Mutex object.
+       * \throws MutexException on initialization failure.
+       */
+      Mutex();
+
+      /** Destroys this Mutex object.
+       */
+      ~Mutex();
+
+      /** Acquire ownership of this Mutex object.
+       * This call will block if another thread has ownership of
+       * this Mutex. When it returns, the current thread is the
+       * owner of this Mutex object.
+       *
+       * In the same thread, this recursive mutex can be acquired
+       * multiple times.
+       *
+       * \throws MutexException if the maximum number of recursive
+       *         locks for mutex has been exceeded.
+       */
+      void lock();
+
+      /** Release ownership of this Mutex object.
+       * If another thread is waiting to acquire the ownership of
+       * this mutex it will stop blocking and acquire ownership
+       * when this call returns.
+       *
+       * \throws MutexException if the current thread does not
+       *         own the mutex.
+       */
+      void unlock();
+
+      /** Try to acquire ownership of this Mutex object.
+       * This call will return false if another thread has ownership
+       * of this Mutex or the maximum number of recursive locks for
+       * mutex has been exceeded.
+       * When it returns true, the current thread is the owner of
+       * this Mutex object.
+       *
+       * \return true, if ownership was acquired.
+       */
+      bool trylock();
+
+    private:
+      RecursiveMutex_t m_mutex;
+    };
+
+
+    //////////////////////////////////////////////////////////////////
+  } // namespace thread
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+} // namespace zypp
+//////////////////////////////////////////////////////////////////////
+
+#endif // ZYPP_THREAD_MUTEX_H
+/*
+** vim: set ts=2 sts=2 sw=2 ai et:
+*/
diff --git a/zypp/thread/MutexException.h b/zypp/thread/MutexException.h
new file mode 100644 (file)
index 0000000..2fd2515
--- /dev/null
@@ -0,0 +1,60 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/thread/MutexException.h
+ *
+*/
+#ifndef   ZYPP_THREAD_MUTEXEXCEPTION_H
+#define   ZYPP_THREAD_MUTEXEXCEPTION_H
+
+#include <zypp/base/Exception.h>
+
+
+//////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ////////////////////////////////////////////////////////////////////
+
+  ////////////////////////////////////////////////////////////////////
+  namespace thread
+  { //////////////////////////////////////////////////////////////////
+
+
+    ////////////////////////////////////////////////////////////////
+    //
+    // CLASS NAME : MutexException
+    //
+    /** Exception type thrown on mutex errors.
+     */
+    class MutexException: public zypp::Exception
+    {
+    public:
+      MutexException()
+        : zypp::Exception( ::zypp::Exception::strErrno(errno))
+      {}
+
+      MutexException(const std::string &msg)
+        : zypp::Exception( msg)
+      {}
+
+      virtual ~MutexException() throw()
+      {}
+    };
+
+
+    //////////////////////////////////////////////////////////////////
+  } // namespace thread
+  ////////////////////////////////////////////////////////////////////
+
+  ////////////////////////////////////////////////////////////////////
+} // namespace zypp
+//////////////////////////////////////////////////////////////////////
+
+#endif // ZYPP_THREAD_MUTEXEXCEPTION_H
+/*
+** vim: set ts=2 sts=2 sw=2 ai et:
+*/
diff --git a/zypp/thread/MutexLock.h b/zypp/thread/MutexLock.h
new file mode 100644 (file)
index 0000000..7c1998c
--- /dev/null
@@ -0,0 +1,102 @@
+/*---------------------------------------------------------------------\
+|                          ____ _   __ __ ___                          |
+|                         |__  / \ / / . \ . \                         |
+|                           / / \ V /|  _/  _/                         |
+|                          / /__ | | | | | |                           |
+|                         /_____||_| |_| |_|                           |
+|                                                                      |
+\---------------------------------------------------------------------*/
+/** \file zypp/thread/MutexLock.h
+ *
+*/
+#ifndef   ZYPP_THREAD_MUTEXLOCK_H
+#define   ZYPP_THREAD_MUTEXLOCK_H
+
+#include <zypp/thread/Mutex.h>
+#include <cassert>
+
+
+//////////////////////////////////////////////////////////////////////
+namespace zypp
+{ ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+  namespace thread
+  { //////////////////////////////////////////////////////////////////
+
+
+    // -------------------------------------------------------------
+    class MutexLock
+    {
+    public:
+      explicit MutexLock(Mutex &mutex, bool init_locked=true)
+        : m_mutex(&mutex)
+        , m_locked(false)
+      {
+        if(init_locked)
+          lock();
+      }
+
+      MutexLock(const MutexLock &ref)
+        : m_mutex( ref.m_mutex)
+        , m_locked(ref.m_locked)
+      {
+        ref.m_locked = false;
+      }
+
+      ~MutexLock()
+      {
+        try
+        {
+          if( m_locked)
+            unlock();
+        }
+        catch( ... )
+        {
+          // don't let exceptions escape
+        }
+      }
+
+      void lock()
+      {
+        assert(m_locked == false);
+        m_mutex->lock();
+        m_locked = true;
+      }
+
+      void unlock()
+      {
+        assert(m_locked == true);
+        m_mutex->unlock();
+        m_locked = false;
+      }
+
+      bool trylock()
+      {
+        assert(m_locked == false);
+        m_locked = m_mutex->trylock();
+        return m_locked;
+      }
+
+      bool locked()
+      {
+        return m_locked;
+      }
+
+    private:
+      Mutex        *m_mutex;
+      mutable bool  m_locked;
+      //friend class Condition;
+    };
+
+
+    //////////////////////////////////////////////////////////////////
+  } // namespace thread
+  ////////////////////////////////////////////////////////////////////
+  ////////////////////////////////////////////////////////////////////
+} // namespace zypp
+//////////////////////////////////////////////////////////////////////
+
+#endif // ZYPP_THREAD_MUTEXLOCK_H
+/*
+** vim: set ts=2 sts=2 sw=2 ai et:
+*/