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

Linux/Unix编程

开发平台:

Unix_Linux

  1. #include <thread.h>
  2. #include <thread_lists.h>
  3. #include <thread_signal_num.h>
  4. #include "wait_queue.h"
  5. #include "shared.h"
  6. extern "C" {
  7. # include <errno.h>
  8. #       include <sys/time.h>
  9. #       include <unistd.h>
  10. #       include <signal.h>
  11. };
  12. char *cond::c_project = 0;
  13. //
  14. // Conditional variables.  This variable consists of a single
  15. // spinlock structure, and a couple of function to control
  16. // activity around it.  And a list of threads that are waiting
  17. // on that condition.
  18. cond::cond(attributes::scope p_scope)
  19. {
  20.   c_id = -1;
  21.   if ( p_scope == attributes::process_shared )
  22.     c_id = shared_mem::share.create_proj( c_project );
  23.   c_waiting = new wait_queue( c_id );
  24.   c_scope = p_scope;
  25. }
  26. cond::cond()
  27. {
  28.   c_waiting = new wait_queue;
  29.   c_scope = attributes::process_private;
  30. }
  31. cond::~cond()
  32. {
  33.   if ( c_waiting->empty() == false )
  34.     broadcast();
  35.   delete c_waiting;
  36. }
  37. attributes::scope cond::scope()
  38. {
  39.   return c_scope;
  40. }
  41. //
  42. // Wait for a signal to arrive through the conditional variable.
  43. // mutex is considered lock on entry, and is unlock during the
  44. // time we wait for the signal to arrive.  The mutex is relocked
  45. // before returning.
  46. int cond::wait(mutex& _mutx)
  47. {
  48.   thread_list::iterator i = thread_list::__threads.locate(getpid());
  49.   if ( i != thread_list::__threads.end()) {
  50.     _mutx.unlock();
  51.     c_waiting->suspend_me();
  52.     _mutx.lock();
  53.     if ((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable) {
  54.       c_waiting->remove((*i)->id());
  55.       (*i)->exit(PTHREAD_CANCELED);
  56.     }
  57.   }
  58.   return 0;
  59. }
  60. //
  61. // timedwait relative.
  62. //
  63. // wait for a specific time, for a signal to arrive, or for a
  64. // cancelation to occur.  As with wait, mutex is considered
  65. // lock on entry, and is unlocked during the wait for the
  66. // signal.  It is relocked, after the duration transpires.
  67. int cond::timedwait_rel(mutex& _mutx, const struct timespec *_spec)
  68. {
  69.   thread_list::iterator i = thread_list::__threads.locate(getpid());
  70.   sigset_t unblock, initial_mask;
  71.   int retsleep = -1;
  72.   sigjmp_buf jmpbuf;
  73.   if (i == thread_list::__threads.end())
  74.     return ESRCH;
  75.   c_waiting->insert((*i)->id());
  76.   _mutx.unlock();
  77.   if (sigsetjmp(jmpbuf, 0) == 0) {
  78.     (*i)->set(pthread::signal_jmp, &jmpbuf);
  79.     (*i)->signal(0);
  80.     if (!((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable)) {
  81.       sigemptyset(&unblock);
  82.       sigaddset(&unblock, PTHREAD_SIG_RESTART);
  83.       sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
  84.       retsleep = nanosleep(_spec, NULL);
  85.       sigprocmask(SIG_SETMASK, &initial_mask, NULL);
  86.     }
  87.   }
  88.   (*i)->set(pthread::signal_jmp, 0);
  89.   if ((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable) {
  90.     c_waiting->remove((*i)->id());
  91.     _mutx.lock();
  92.     (*i)->exit(PTHREAD_CANCELED);
  93.   }
  94.   if ((*i)->signal() == 0) {
  95.     c_waiting->remove((*i)->id());
  96.     _mutx.lock();
  97.     return retsleep ? EINTR : ETIMEDOUT;
  98.   }
  99.   _mutx.lock();
  100.   return 0;
  101. }
  102. //
  103. // timedwait
  104. //
  105. // Wait for a specific time period, for a signal to occur.  This
  106. // routine simple calculates the relative time, from the given
  107. // time and current time.  Then uses timedwait relative to
  108. // perform the actual wait.
  109. int cond::timedwait(mutex& _mutx, const struct timespec *_spec)
  110. {
  111.   struct timeval now;
  112.   struct timespec reltime;
  113.   gettimeofday(&now, NULL);
  114.   reltime.tv_sec = _spec->tv_sec - now.tv_sec;
  115.   reltime.tv_nsec = _spec->tv_nsec - now.tv_usec * 1000;
  116.   if (reltime.tv_nsec < 0) {
  117.     reltime.tv_nsec += 1000000000;
  118.     reltime.tv_sec -= 1;
  119.   }
  120.   if (reltime.tv_sec < 0)
  121.     return ETIMEDOUT;
  122.   return timedwait_rel(_mutx, &reltime);
  123. }
  124. //
  125. // signal
  126. //
  127. // send a signal to the next process waiting on the list.
  128. int cond::signal()
  129. {
  130.   c_waiting->wake_up();
  131.   return 0;
  132. }
  133. //
  134. // broadcast
  135. //
  136. // send a signal to every process on the list.
  137. int cond::broadcast()
  138. {
  139.   while( !c_waiting->empty() )
  140.     c_waiting->wake_up();
  141.   return 0;
  142. }
  143. //
  144. // project_part
  145. //
  146. // change the project part
  147. void
  148. cond::project_part(const char *p_part)
  149. {
  150.   if ( c_project == 0 )
  151.     c_project = new char[80];
  152.   c_project[0] = 0;
  153.   if ( p_part )
  154.     strcpy( c_project,p_part );
  155. }