cond.C
上传用户:shtangtang
上传日期:2007-01-04
资源大小:167k
文件大小:4k
- #include <thread.h>
- #include <thread_lists.h>
- #include <thread_signal_num.h>
- #include "wait_queue.h"
- #include "shared.h"
- extern "C" {
- # include <errno.h>
- # include <sys/time.h>
- # include <unistd.h>
- # include <signal.h>
- };
- char *cond::c_project = 0;
- //
- // Conditional variables. This variable consists of a single
- // spinlock structure, and a couple of function to control
- // activity around it. And a list of threads that are waiting
- // on that condition.
- cond::cond(attributes::scope p_scope)
- {
- c_id = -1;
- if ( p_scope == attributes::process_shared )
- c_id = shared_mem::share.create_proj( c_project );
- c_waiting = new wait_queue( c_id );
- c_scope = p_scope;
- }
- cond::cond()
- {
- c_waiting = new wait_queue;
- c_scope = attributes::process_private;
- }
- cond::~cond()
- {
- if ( c_waiting->empty() == false )
- broadcast();
- delete c_waiting;
- }
- attributes::scope cond::scope()
- {
- return c_scope;
- }
- //
- // Wait for a signal to arrive through the conditional variable.
- // mutex is considered lock on entry, and is unlock during the
- // time we wait for the signal to arrive. The mutex is relocked
- // before returning.
- int cond::wait(mutex& _mutx)
- {
- thread_list::iterator i = thread_list::__threads.locate(getpid());
- if ( i != thread_list::__threads.end()) {
- _mutx.unlock();
- c_waiting->suspend_me();
- _mutx.lock();
- if ((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable) {
- c_waiting->remove((*i)->id());
- (*i)->exit(PTHREAD_CANCELED);
- }
- }
- return 0;
- }
- //
- // timedwait relative.
- //
- // wait for a specific time, for a signal to arrive, or for a
- // cancelation to occur. As with wait, mutex is considered
- // lock on entry, and is unlocked during the wait for the
- // signal. It is relocked, after the duration transpires.
- int cond::timedwait_rel(mutex& _mutx, const struct timespec *_spec)
- {
- thread_list::iterator i = thread_list::__threads.locate(getpid());
- sigset_t unblock, initial_mask;
- int retsleep = -1;
- sigjmp_buf jmpbuf;
- if (i == thread_list::__threads.end())
- return ESRCH;
- c_waiting->insert((*i)->id());
- _mutx.unlock();
- if (sigsetjmp(jmpbuf, 0) == 0) {
- (*i)->set(pthread::signal_jmp, &jmpbuf);
- (*i)->signal(0);
- if (!((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable)) {
- sigemptyset(&unblock);
- sigaddset(&unblock, PTHREAD_SIG_RESTART);
- sigprocmask(SIG_UNBLOCK, &unblock, &initial_mask);
- retsleep = nanosleep(_spec, NULL);
- sigprocmask(SIG_SETMASK, &initial_mask, NULL);
- }
- }
- (*i)->set(pthread::signal_jmp, 0);
- if ((*i)->canceled() && (*i)->cancelstate() == pthread::cancel_enable) {
- c_waiting->remove((*i)->id());
- _mutx.lock();
- (*i)->exit(PTHREAD_CANCELED);
- }
- if ((*i)->signal() == 0) {
- c_waiting->remove((*i)->id());
- _mutx.lock();
- return retsleep ? EINTR : ETIMEDOUT;
- }
- _mutx.lock();
- return 0;
- }
- //
- // timedwait
- //
- // Wait for a specific time period, for a signal to occur. This
- // routine simple calculates the relative time, from the given
- // time and current time. Then uses timedwait relative to
- // perform the actual wait.
- int cond::timedwait(mutex& _mutx, const struct timespec *_spec)
- {
- struct timeval now;
- struct timespec reltime;
- gettimeofday(&now, NULL);
- reltime.tv_sec = _spec->tv_sec - now.tv_sec;
- reltime.tv_nsec = _spec->tv_nsec - now.tv_usec * 1000;
- if (reltime.tv_nsec < 0) {
- reltime.tv_nsec += 1000000000;
- reltime.tv_sec -= 1;
- }
- if (reltime.tv_sec < 0)
- return ETIMEDOUT;
- return timedwait_rel(_mutx, &reltime);
- }
- //
- // signal
- //
- // send a signal to the next process waiting on the list.
- int cond::signal()
- {
- c_waiting->wake_up();
- return 0;
- }
- //
- // broadcast
- //
- // send a signal to every process on the list.
- int cond::broadcast()
- {
- while( !c_waiting->empty() )
- c_waiting->wake_up();
- return 0;
- }
- //
- // project_part
- //
- // change the project part
- void
- cond::project_part(const char *p_part)
- {
- if ( c_project == 0 )
- c_project = new char[80];
- c_project[0] = 0;
- if ( p_part )
- strcpy( c_project,p_part );
- }