📄 cond.c
字号:
#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 partvoidcond::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 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -