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

Linux/Unix编程

开发平台:

Unix_Linux

  1. //
  2. // Semaphores
  3. //
  4. // This is a basic semaphore implementation, not very rich.
  5. //
  6. #include <iostream.h>
  7. #include <thread.h>
  8. #include <thread_lists.h>
  9. #include "wait_queue.h"
  10. #include "thread_semaphore.h"
  11. #include "shared.h"
  12. char *semaphore::s_project = 0;
  13. semaphore::semaphore(attributes::scope p_scope)
  14. {
  15.   if ( p_scope == attributes::process_private )
  16.     _s = new storage;
  17.   else {
  18.     s_id = shared_mem::share.create_proj( s_project );
  19.     _s = (storage *)shared_mem::share.alloc( sizeof(storage),s_id );
  20.   }
  21.   s_waiting = new wait_queue(s_id);
  22.   s_scope = p_scope;
  23.   if ( _s->s_magic != 0x212610 ) {
  24.     _s->s_count = 0;
  25.     _s->s_magic = 0x212610;
  26.   }
  27. }
  28. semaphore::semaphore(attributes::scope p_scope, int p_count)
  29. {
  30.   if ( p_scope == attributes::process_private )
  31.     _s = new storage;
  32.   else {
  33.     s_id = shared_mem::share.create_proj("sem");
  34.     key_t key = shared_mem::share.make_key( s_id );
  35.     _s = (storage *)shared_mem::share.alloc( key,sizeof(storage) );
  36.   }
  37.   s_waiting = new wait_queue(s_id);
  38.   s_scope = p_scope;
  39.   if ( _s->s_magic != 0x212610 ) {
  40.     _s->s_count = p_count;
  41.     _s->s_magic = 0x212610;
  42.   }
  43. }
  44. semaphore::semaphore()
  45. {
  46.   s_waiting   = new wait_queue;
  47.   _s          = new storage;
  48.   _s->s_count = 0;
  49.   s_scope = attributes::process_private;
  50. }
  51. semaphore::semaphore(int p_count)
  52. {
  53.   s_waiting   = new wait_queue;
  54.   _s          = new storage;
  55.   _s->s_count = p_count;
  56.   s_scope = attributes::process_private;
  57. }
  58. semaphore::~semaphore()
  59. {
  60.   if ( _s ) {
  61.     delete s_waiting;
  62.     if ( s_scope == attributes::process_private )
  63.       delete _s;
  64.     else
  65.       shared_mem::share.dealloc( _s );
  66.     _s = 0;
  67.   }
  68. }
  69. //
  70. // post()
  71. //
  72. // Increment the count associated with the semaphore, and restart
  73. // any processes that are blocking on it.
  74. int
  75. semaphore::post()
  76. {
  77.   int rval;
  78.   _s->s_sync.acquire();
  79.   rval = ++_s->s_count;
  80.   s_waiting->wake_up();
  81.   _s->s_sync.release();
  82.   return rval;
  83. }
  84. //
  85. // wait
  86. //
  87. // Wait until a semaphore becomes non-zero, then atomically
  88. // decrement it and return with the current count of the
  89. // semaphore.
  90. int
  91. semaphore::wait()
  92. {
  93.   thread_list::iterator i = thread_list::__threads.locate(getpid());
  94.   int val = -1;
  95.   if (i != thread_list::__threads.end()) {
  96.     _s->s_sync.acquire();
  97.     if ( _s->s_count == 0 ) {
  98.       s_waiting->insert((*i)->id());
  99.       _s->s_sync.release();
  100.       (*i)->suspend_with_cancelation();
  101.       _s->s_sync.acquire();
  102.       if ((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable) {
  103. s_waiting->remove((*i)->id());
  104. _s->s_sync.release();
  105. (*i)->exit(PTHREAD_CANCELED);
  106.       }
  107.       if ( _s->s_count > 0 )
  108. _s->s_count--;
  109.     } else
  110.       _s->s_count--;
  111.     val = _s->s_count;
  112.     _s->s_sync.release();
  113.   }
  114.   return val;
  115. }
  116. //
  117. // trywait
  118. //
  119. // This will decrement the semaphore by one, without blocking it.
  120. // it will return with -1, if the semaphore could not be decremented,
  121. // and the current semaphore count otherwise.
  122. int
  123. semaphore::trywait()
  124. {
  125.   int retcode = 0;
  126.   _s->s_sync.acquire();
  127.   retcode = _s->s_count;
  128.   if ( retcode-- > 0 )
  129.     _s->s_count--;
  130.   _s->s_sync.release();
  131.   return retcode;
  132. }
  133. //
  134. // project_part
  135. //
  136. // change the project part
  137. void
  138. semaphore::project_part(const char *p_part)
  139. {
  140.   if ( s_project == 0 )
  141.     s_project = new char[80];
  142.   s_project[0] = 0;
  143.   if ( p_part )
  144.     strcpy( s_project,p_part );
  145. }