mutex.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_UTILITIES_MUTEX_H
00021 #define ARCHON_UTILITIES_MUTEX_H
00022 
00023 #include <errno.h>
00024 #include <pthread.h>
00025 
00026 #include <archon/util/exception.H>
00027 
00028 namespace Archon
00029 {
00030   namespace Utilities
00031   {
00032     using namespace std;
00033 
00034     struct Thread;
00035     struct Condition;
00036 
00040     struct Mutex
00041     {
00042       Mutex()
00043       {
00044         const int e = pthread_mutex_init(&mutex, 0);
00045         if(e != 0)
00046           ARCHON_THROW1(ResourceException,
00047                         "Mutex initialization failed");
00048       }
00049 
00050       ~Mutex()
00051       {
00052         const int e = pthread_mutex_destroy(&mutex);
00053         if(e != 0)
00054         {
00055           if(e == EBUSY)
00056             ARCHON_THROW1(StateException,
00057                           "Attempt to delete a locked mutex");
00058           ARCHON_THROW1(InternalException,
00059                         "Mutex destruction failed");
00060         }
00061       }
00062 
00102       struct Lock
00103       {
00110         Lock(): mutex(0) {}
00111 
00115         Lock(const Mutex &m): mutex(&m)
00116         {
00117           m.lock();
00118         }
00119 
00120         ~Lock()
00121         {{ // The extra scope is needed to work around gcc3.2 bug #8287
00122           release();
00123         }}
00124 
00129         void aquire(const Mutex &m)
00130         {
00131           release();
00132           m.lock();
00133           mutex = &m;
00134         }
00135 
00140         void release()
00141         {
00142           if(!mutex) return;
00143           mutex->unlock();
00144           mutex = 0;
00145         }
00146 
00147       private:
00148         friend struct Thread;
00149 
00150         const Mutex *mutex;
00151 
00152         Lock(const Lock &); // Hide
00153         Lock &operator=(const Lock &); // Hide
00154       };
00155 
00156     private:
00157       friend struct Condition;
00158 
00159       pthread_mutex_t mutex;
00160 
00161       Mutex(const Mutex &); // Hide
00162       Mutex &operator=(const Mutex &); // Hide
00163 
00170       void lock() const
00171       {
00172         const int e =
00173           pthread_mutex_lock(const_cast<pthread_mutex_t *>(&mutex));
00174         if(e == 0) return;
00175         if(e == EDEADLK)
00176           ARCHON_THROW1(StateException,
00177                         "Attempt to lock a locked mutex");
00178         if(e == EINVAL)
00179           ARCHON_THROW1(InternalException,
00180                         "Attempt to lock uninitialized mutex");
00181         ARCHON_THROW1(InternalException,
00182                       "Attempt to lock mutex failed");
00183       }
00184 
00185       void unlock() const
00186       {
00187         const int e =
00188           pthread_mutex_unlock(const_cast<pthread_mutex_t *>(&mutex));
00189         if(e == 0) return;
00190         if(e == EPERM)
00191           ARCHON_THROW1(StateException,
00192                         "Attempt to unlock mutex that is locked by another thread");
00193         if(e == EINVAL)
00194           ARCHON_THROW1(InternalException,
00195                         "Attempt to unlock uninitialized mutex");
00196         ARCHON_THROW1(InternalException,
00197                       "Attempt to unlock mutex failed");
00198       }
00199     };
00200   }
00201 }
00202 
00203 #endif // ARCHON_UTILITIES_MUTEX_H

Generated on Sun Jul 30 22:55:45 2006 for Archon by  doxygen 1.4.4