mutex.C
上传用户:shtangtang
上传日期:2007-01-04
资源大小:167k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. //
  2. // class mutex
  3. //
  4. // Mutes is a semaphore, that can be used by two threads to mutually
  5. // exclude the other.  To ensure uniqe access to memory.
  6. #include <thread_mutex.h>
  7. #include <thread_lists.h>
  8. #include "wait_queue.h"
  9. #include "shared.h"
  10. extern "C" {
  11. # include <errno.h>
  12. #       include <unistd.h>
  13. };
  14. char *mutex::m_project = 0;
  15. mutex::mutex(attributes::scope p_scope)
  16. {
  17.   init( p_scope );
  18. }
  19. mutex::mutex()
  20. {
  21.   init( attributes::process_private );
  22. }
  23. mutex::~mutex()
  24. {
  25.   if ( _m ) {
  26.     delete m_waiting;
  27.     if ( m_scope == attributes::process_private )
  28.       delete _m;
  29.     else 
  30.       shared_mem::share.dealloc( _m );
  31.     _m = 0;
  32.   }
  33. }
  34. void mutex::init(attributes::scope p_scope)
  35. {
  36.   m_id = -1;
  37.   if ( p_scope == attributes::process_private ) {
  38.     _m            = new storage;
  39.     _m->m_magic   = 0;
  40.   } else {
  41.    m_id           = shared_mem::share.create_proj( m_project );
  42.    _m             = (storage *)shared_mem::share.alloc( sizeof(storage),m_id );
  43.    assert( _m != (storage *)-1 );
  44.   }
  45.   if ( _m->m_magic != 0x212612 ) {
  46.     _m->m_kind    = fast;
  47.     _m->m_count   = 0;
  48.     _m->m_owner   = -1;
  49.     _m->m_magic   = 0x212612;
  50.   }
  51.   m_waiting       = new wait_queue( m_id );
  52.   m_scope         = p_scope;
  53. }
  54. attributes::scope mutex::scope()
  55. {
  56.   return m_scope;
  57. }
  58. void mutex::release()
  59. {
  60.   _m->m_owner = 0;
  61.   _m->m_count = 0;
  62. }
  63. int mutex::acquire()
  64. {
  65.   _m->m_owner = getpid();
  66.   _m->m_count++;
  67.   return 0;
  68. }
  69. //
  70. // kind
  71. //
  72. // set the mutex kind.
  73. int mutex::kind(mutex_kind _kind)
  74. {
  75.   if (_kind != mutex::recursive && _kind != mutex::fast)
  76.     return EINVAL;
  77.   _m->m_kind = _kind;
  78.   return 0;
  79. }
  80. //
  81. // kind
  82. //
  83. // get the mutex kind.
  84. int mutex::kind()
  85. {
  86.   return _m->m_kind;
  87. }
  88. //
  89. // trylock
  90. //
  91. // try and lock the mutex.
  92. //
  93. // return
  94. //   EBUSY  - the mutex is locked by another.
  95. //   EINVAL - the mutex is of an unknown kind.
  96. //   0      - successful.
  97. int mutex::trylock()
  98. {
  99.   int rval = EBUSY;
  100.   _m->m_spinlock.acquire();
  101.   switch(_m->m_kind) {
  102.   case mutex::fast:
  103.     if ( _m->m_count == 0 )
  104.       rval = acquire();
  105.     break;
  106.   case mutex::recursive:
  107.     if (_m->m_count == 0 || _m->m_owner == getpid())
  108.       rval = acquire();
  109.     break;
  110.   case mutex::errorcheck:
  111.     if ( _m->m_count == 0 )
  112.       rval = acquire();
  113.     else
  114.       if ( _m->m_owner == getpid() )
  115. rval = EDEADLK;
  116.     break;
  117.   default:
  118.     rval = EINVAL;
  119.     break;
  120.   }
  121.   _m->m_spinlock.release();
  122.   return rval;
  123. }
  124. //
  125. // lock
  126. //
  127. // Try and lock the mutex.  If unsuccessful, suspend the calling
  128. // process, until the mutex is available.
  129. int mutex::lock()
  130. {
  131.   int rval = EBUSY;
  132.   while(rval == EBUSY) {
  133.     if ((rval = trylock()) == EBUSY)
  134.       m_waiting->suspend_me();
  135.   }
  136.   return rval;
  137. }
  138. //
  139. // unlock
  140. //
  141. // unlock the mutex, and restart any threads, that are waiting
  142. // on it.
  143. int mutex::unlock()
  144. {
  145.   int rval = 0;
  146.   _m->m_spinlock.acquire();
  147.   switch(_m->m_kind) {
  148.   case mutex::fast:
  149.     if ( _m->m_owner == getpid() )
  150.       release();
  151.     else
  152.       rval = EBUSY;
  153.     break;
  154.   case mutex::recursive:
  155.     if ( _m->m_owner == getpid() ) {
  156.       if (--_m->m_count <= 1)
  157. release();
  158.     } else
  159.       rval = EBUSY;
  160.     break;
  161.   case mutex::errorcheck:
  162.     if ( _m->m_count == 0 || _m->m_owner != getpid() )
  163.       rval = EPERM;
  164.     else
  165.       release();
  166.     break;
  167.   default:
  168.     rval = EINVAL;
  169.   }
  170.   _m->m_spinlock.release();
  171.   if ( rval == 0 )
  172.     m_waiting->wake_up();
  173.   return rval;
  174. }
  175. //
  176. // project_part
  177. //
  178. // change the project part
  179. void
  180. mutex::project_part(const char *p_part)
  181. {
  182.   if ( m_project == 0 )
  183.     m_project = new char[80];
  184.   m_project[0] = 0;
  185.   if ( p_part )
  186.     strcpy( m_project,p_part );
  187. }