int env_remove(const wcstring &key, int var_mode) { ASSERT_IS_MAIN_THREAD(); env_node_t *first_node; int erased = 0; if ((var_mode & ENV_USER) && is_read_only(key)) { return 2; } first_node = top; if (!(var_mode & ENV_UNIVERSAL)) { if (var_mode & ENV_GLOBAL) { first_node = global_env; } if (try_remove(first_node, key.c_str(), var_mode)) { event_t ev = event_t::variable_event(key); ev.arguments.push_back(L"VARIABLE"); ev.arguments.push_back(L"ERASE"); ev.arguments.push_back(key); event_fire(&ev); erased = 1; } } if (!erased && !(var_mode & ENV_GLOBAL) && !(var_mode & ENV_LOCAL)) { bool is_exported = uvars()->get_export(key); erased = uvars() && uvars()->remove(key); if (erased) { env_universal_barrier(); event_t ev = event_t::variable_event(key); ev.arguments.push_back(L"VARIABLE"); ev.arguments.push_back(L"ERASE"); ev.arguments.push_back(key); event_fire(&ev); } if (is_exported) mark_changed_exported(); } react_to_variable_change(key); return !erased; }
static void * worker_thread(void *arg) #endif { per_thread_state_t *pth = arg; while (event_wait(pth->evpro) && !pth->done) { if (pth->flow(pth) < 0) pth->error = sox_true; event_fire(pth->evcon); } event_fire(pth->evcon); return 0; }
/** Handle interruptions to key reading by reaping finshed jobs and propagating the interrupt to the reader. */ static int interrupt_handler() { /* Fire any pending events */ event_fire( 0 ); /* Reap stray processes, including printing exit status messages */ if( job_reap( 1 ) ) reader_repaint_needed(); /* Tell the reader an event occured */ if( reader_interrupted() ) { /* Return 3, i.e. the character read by a Control-C. */ return 3; } return R_NULL; }
/// Universal variable callback function. This function makes sure the proper events are triggered /// when an event occurs. static void universal_callback(fish_message_type_t type, const wchar_t *name) { const wchar_t *str = NULL; switch (type) { case SET: case SET_EXPORT: { str = L"SET"; break; } case ERASE: { str = L"ERASE"; break; } default: { assert(0 && "Unhandled fish_message_type_t constant!"); abort(); } } if (str) { mark_changed_exported(); event_t ev = event_t::variable_event(name); ev.arguments.push_back(L"VARIABLE"); ev.arguments.push_back(str); ev.arguments.push_back(name); event_fire(&ev); } if (name) react_to_variable_change(name); }
/// Callback for firing (and then deleting) an event. static void fire_event_callback(void *arg) { ASSERT_IS_MAIN_THREAD(); assert(arg != NULL); event_t *event = static_cast<event_t *>(arg); event_fire(event); delete event; }
void proc_fire_event(const wchar_t *msg, int type, pid_t pid, int status) { event.type = type; event.param1.pid = pid; event.arguments.push_back(msg); event.arguments.push_back(to_string<int>(pid)); event.arguments.push_back(to_string<int>(status)); event_fire(&event); event.arguments.resize(0); }
int env_remove( const wcstring &key, int var_mode ) { ASSERT_IS_MAIN_THREAD(); env_node_t *first_node; int erased = 0; if( (var_mode & ENV_USER ) && is_read_only(key) ) { return 2; } first_node = top; if( ! (var_mode & ENV_UNIVERSAL ) ) { if( var_mode & ENV_GLOBAL ) { first_node = global_env; } if( try_remove( first_node, key.c_str(), var_mode ) ) { event_t ev = event_t::variable_event(key); ev.arguments.reset(new wcstring_list_t); ev.arguments->push_back(L"VARIABLE"); ev.arguments->push_back(L"ERASE"); ev.arguments->push_back(key); event_fire( &ev ); ev.arguments.reset(NULL); erased = 1; } } if( !erased && !(var_mode & ENV_GLOBAL) && !(var_mode & ENV_LOCAL) ) { erased = ! env_universal_remove( key.c_str() ); } react_to_variable_change(key); return !erased; }
static int fire_and_wait_workers(lsx_thread_state_t *state, sox_bool join) { int i, n = 0; for (i = 0; i < state->count; ++i) { per_thread_state_t *ts = &state->pth[i]; if (ts->ht) event_fire(ts->evpro); } for (i = 0; i < state->count; ++i) { per_thread_state_t *ts = &state->pth[i]; if (ts->ht) { if (join) thread_join(ts->ht); else event_wait(ts->evcon); } } return 0; }
/** Universal variable callback function. This function makes sure the proper events are triggered when an event occurs. */ static void universal_callback( fish_message_type_t type, const wchar_t *name, const wchar_t *val ) { const wchar_t *str=0; switch( type ) { case SET: case SET_EXPORT: { str=L"SET"; break; } case ERASE: { str=L"ERASE"; break; } default: break; } if( str ) { mark_changed_exported(); event_t ev = event_t::variable_event(name); ev.arguments.reset(new wcstring_list_t()); ev.arguments->push_back(L"VARIABLE"); ev.arguments->push_back(str); ev.arguments->push_back(name); event_fire( &ev ); ev.arguments.reset(NULL); } if (name) react_to_variable_change(name); }
int event_parse(SDL_Event ev) { switch(ev.type) { case SDL_KEYDOWN: return event_key(ev.key, EVENT_PRESS); case SDL_KEYUP: return event_key(ev.key, EVENT_RELEASE); case SDL_MOUSEMOTION: return event_mouse(ev.motion); case SDL_MOUSEBUTTONDOWN: return event_button(ev.button, EVENT_PRESS); case SDL_MOUSEBUTTONUP: return event_button(ev.button, EVENT_RELEASE); case SDL_JOYAXISMOTION: return event_joystick(ev.jaxis); case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: return event_fire(ev.jbutton); case SDL_WINDOWEVENT: if(ev.window.windowID == screen_window_id) { if(ev.window.event == SDL_WINDOWEVENT_RESIZED) { if((ev.window.data1 % 512) == 0 && (ev.window.data2 % 314) == 0) screen_make_texture(SDL_SCALING_NEAREST); else screen_make_texture(SDL_SCALING_LINEAR); } } break; case SDL_QUIT: if(debugger) return EVENT_DEBUG; else { SDL_Quit(); exit(0); } } return EVENT_NONE; }
static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_KERNEL *ev = (EVENT_KERNEL *) eventp; ACL_EVENT_NOTIFY_TIME timer_fn; void *timer_arg; ACL_EVENT_TIMER *timer; int delay, nready; ACL_EVENT_FDTABLE *fdp; EVENT_BUFFER *bp; delay = (int) (eventp->delay_sec * 1000 + eventp->delay_usec / 1000); if (delay < 0) delay = 0; /* 0 milliseconds at least */ /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); /* 根据定时器任务的最近任务计算 epoll/kqueue/devpoll 的检测超时上限 */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = (timer->when - eventp->present) / 1000; if (n <= 0) delay = 0; else if ((int) n < delay) { delay = (int) n; if (delay <= 0) /* xxx */ delay = 100; } } /* 设置描述字对象的状态,添加/删除之前设置的描述字对象 */ event_set_all(eventp); if (eventp->fdcnt == 0) { if (eventp->fdcnt_ready == 0) sleep(1); goto TAG_DONE; } /* 如果已经有描述字准备好则检测超时时间置 0 */ if (eventp->fdcnt_ready > 0) delay = 0; /* 调用 epoll/kquque/devpoll 系统调用检测可用描述字 */ EVENT_BUFFER_READ(nready, ev->event_fd, ev->event_buf, ev->event_fdslots, delay); if (eventp->nested++ > 0) acl_msg_fatal("%s(%d): recursive call, nested: %d", myname, __LINE__, eventp->nested); if (nready < 0) { if (acl_last_error() != ACL_EINTR) { acl_msg_fatal("%s(%d), %s: select: %s", __FILE__, __LINE__, myname, acl_last_serror()); } goto TAG_DONE; } else if (nready == 0) goto TAG_DONE; /* 检查检测结果 */ for (bp = ev->event_buf; bp < ev->event_buf + nready; bp++) { #ifdef USE_FDMAP ACL_SOCKET sockfd; sockfd = EVENT_GET_FD(bp); fdp = acl_fdmap_ctx(ev->fdmap, sockfd); if (fdp == NULL || fdp->stream == NULL) continue; if (sockfd != ACL_VSTREAM_SOCK(fdp->stream)) acl_msg_fatal("%s(%d): sockfd(%d) != %d", myname, __LINE__, sockfd, ACL_VSTREAM_SOCK(fdp->stream)); #else fdp = (ACL_EVENT_FDTABLE *) EVENT_GET_CTX(bp); if (fdp == NULL || fdp->stream == NULL) continue; #endif /* 如果该描述字对象已经在被设置为异常或超时状态则继续 */ if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) continue; /* 检查描述字是否可读 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_READ) && EVENT_TEST_READ(bp)) { /* 该描述字可读则设置 ACL_VSTREAM 的系统可读标志从而触发 * ACL_VSTREAM 流在读时调用系统的 read 函数 */ fdp->stream->sys_read_ready = 1; /* 给该描述字对象附加可读属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; if (fdp->listener) fdp->event_type |= ACL_EVENT_ACCEPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } /* 检查描述字是否可写 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_WRITE) && EVENT_TEST_WRITE(bp)) { /* 给该描述字对象附加可写属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } #ifdef EVENT_TEST_ERROR if (EVENT_TEST_ERROR(bp)) { /* 如果出现异常则设置异常属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready++] = fdp; } } #endif } TAG_DONE: /* * Deliver timer events. Requests are sorted: we can stop when we reach * the future or the list end. Allow the application to update the timer * queue while it is being called back. To this end, we repeatedly pop * the first request off the timer queue before delivering the event to * the application. */ /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { if (timer->when > eventp->present) break; timer_fn = timer->callback; timer_arg = timer->context; /* 定时器时间间隔 > 0 且允许定时器被循环调用,则重设定时器 */ if (timer->delay > 0 && timer->keep) { timer->ncount++; eventp->timer_request(eventp, timer->callback, timer->context, timer->delay, timer->keep); } else { acl_ring_detach(&timer->ring); /* first this */ timer->nrefer--; if (timer->nrefer != 0) acl_msg_fatal("%s(%d): nrefer(%d) != 0", myname, __LINE__, timer->nrefer); acl_myfree(timer); } timer_fn(ACL_EVENT_TIME, eventp, timer_arg); } /* 处理准备好的描述字事件 */ if (eventp->fdcnt_ready > 0) event_fire(eventp); eventp->nested--; }
int env_set(const wcstring &key, const wchar_t *val, env_mode_flags_t var_mode) { ASSERT_IS_MAIN_THREAD(); bool has_changed_old = has_changed_exported; bool has_changed_new = false; int done=0; if (val && contains(key, L"PWD", L"HOME")) { /* Canoncalize our path; if it changes, recurse and try again. */ wcstring val_canonical = val; path_make_canonical(val_canonical); if (val != val_canonical) { return env_set(key, val_canonical.c_str(), var_mode); } } if ((var_mode & (ENV_LOCAL | ENV_UNIVERSAL)) && (is_read_only(key) || is_electric(key))) { return ENV_SCOPE; } if ((var_mode & ENV_EXPORT) && is_electric(key)) { return ENV_SCOPE; } if ((var_mode & ENV_USER) && is_read_only(key)) { return ENV_PERM; } if (key == L"umask") { wchar_t *end; /* Set the new umask */ if (val && wcslen(val)) { errno=0; long mask = wcstol(val, &end, 8); if (!errno && (!*end) && (mask <= 0777) && (mask >= 0)) { umask(mask); /* Do not actually create a umask variable, on env_get, it will be calculated dynamically */ return 0; } } return ENV_INVALID; } /* Zero element arrays are internaly not coded as null but as this placeholder string */ if (!val) { val = ENV_NULL; } if (var_mode & ENV_UNIVERSAL) { const bool old_export = uvars() && uvars()->get_export(key); bool new_export; if (var_mode & ENV_EXPORT) { // export new_export = true; } else if (var_mode & ENV_UNEXPORT) { // unexport new_export = false; } else { // not changing the export new_export = old_export; } if (uvars()) { uvars()->set(key, val, new_export); env_universal_barrier(); if (old_export || new_export) { mark_changed_exported(); } } } else { // Determine the node env_node_t *preexisting_node = env_get_node(key); bool preexisting_entry_exportv = false; if (preexisting_node != NULL) { var_table_t::const_iterator result = preexisting_node->env.find(key); assert(result != preexisting_node->env.end()); const var_entry_t &entry = result->second; if (entry.exportv) { preexisting_entry_exportv = true; has_changed_new = true; } } env_node_t *node = NULL; if (var_mode & ENV_GLOBAL) { node = global_env; } else if (var_mode & ENV_LOCAL) { node = top; } else if (preexisting_node != NULL) { node = preexisting_node; if ((var_mode & (ENV_EXPORT | ENV_UNEXPORT)) == 0) { // use existing entry's exportv var_mode = preexisting_entry_exportv ? ENV_EXPORT : 0; } } else { if (! get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); } if (uvars() && ! uvars()->get(key).missing()) { bool exportv; if (var_mode & ENV_EXPORT) { exportv = true; } else if (var_mode & ENV_UNEXPORT) { exportv = false; } else { exportv = uvars()->get_export(key); } uvars()->set(key, val, exportv); env_universal_barrier(); done = 1; } else { /* New variable with unspecified scope. The default scope is the innermost scope that is shadowing, which will be either the current function or the global scope. */ node = top; while (node->next && !node->new_scope) { node = node->next; } } } if (!done) { // Set the entry in the node // Note that operator[] accesses the existing entry, or creates a new one var_entry_t &entry = node->env[key]; if (entry.exportv) { // this variable already existed, and was exported has_changed_new = true; } entry.val = val; if (var_mode & ENV_EXPORT) { // the new variable is exported entry.exportv = true; node->exportv = true; has_changed_new = true; } else { entry.exportv = false; } if (has_changed_old || has_changed_new) mark_changed_exported(); } } event_t ev = event_t::variable_event(key); ev.arguments.reserve(3); ev.arguments.push_back(L"VARIABLE"); ev.arguments.push_back(L"SET"); ev.arguments.push_back(key); // debug( 1, L"env_set: fire events on variable %ls", key ); event_fire(&ev); // debug( 1, L"env_set: return from event firing" ); react_to_variable_change(key); return 0; }
static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_SELECT *ev = (EVENT_SELECT *) eventp; ACL_EVENT_NOTIFY_TIME timer_fn; void *timer_arg; ACL_SOCKET sockfd; ACL_EVENT_TIMER *timer; int nready, i; acl_int64 delay; ACL_EVENT_FDTABLE *fdp; struct timeval tv, *tvp; fd_set rmask; /* enabled read events */ fd_set wmask; /* enabled write events */ fd_set xmask; /* for bad news mostly */ delay = eventp->delay_sec * 1000000 + eventp->delay_usec; /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); /* 根据定时器任务的最近任务计算 select 的检测超时上限 */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = timer->when - eventp->present; if (n <= 0) delay = 0; else if (n < delay) delay = n; } /* 调用 event_prepare 检查有多少个描述字需要通过 select 进行检测 */ if (event_prepare(eventp) == 0) { if (eventp->ready_cnt == 0) { delay /= 1000000; if (delay <= 0) delay = 1; /* 为避免循环过快,休眠一下 */ sleep((int) delay); } goto TAG_DONE; } if (eventp->ready_cnt > 0) { tv.tv_sec = 0; tv.tv_usec = 0; tvp = &tv; } else if (delay >= 0) { #if defined(ACL_WINDOWS) tv.tv_sec = (long) delay / 1000000; tv.tv_usec = (unsigned long) (delay - tv.tv_sec * 1000000); #else tv.tv_sec = (time_t) delay / 1000000; tv.tv_usec = (suseconds_t) (delay - tv.tv_sec * 1000000); #endif tvp = &tv; } else tvp = NULL; rmask = ev->rmask; wmask = ev->wmask; xmask = ev->xmask; /* 调用 select 系统调用检测可用描述字 */ #ifdef ACL_WINDOWS nready = select(0, &rmask, &wmask, &xmask, tvp); #else nready = select(eventp->maxfd + 1, &rmask, &wmask, &xmask, tvp); #endif if (eventp->nested++ > 0) acl_msg_fatal("%s(%d): recursive call(%d)", myname, __LINE__, eventp->nested); if (nready < 0) { if (acl_last_error() != ACL_EINTR) { acl_msg_fatal("%s(%d), %s: select: %s", __FILE__, __LINE__, myname, acl_last_serror()); } goto TAG_DONE; } else if (nready == 0) goto TAG_DONE; /* 检查 select 的检测结果集合 */ /* if some fdp was cleared from eventp->fdtabs in timer callback, * which has no effection on the rest fdp in eventp->fdtabs */ for (i = 0; i < eventp->fdcnt; i++) { fdp = eventp->fdtabs[i]; /* 如果该描述字对象已经在被设置为异常或超时状态则继续 */ if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) continue; sockfd = ACL_VSTREAM_SOCK(fdp->stream); /* 检查描述字是否出现异常 */ if (FD_ISSET(sockfd, &xmask)) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; continue; } /* 检查描述字是否可读 */ if (FD_ISSET(sockfd, &rmask)) { /* 给该描述字对象附加可读属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; } if (fdp->listener) fdp->event_type |= ACL_EVENT_ACCEPT; /* 该描述字可读则设置 ACL_VSTREAM 的系统可读标志从而 * 触发 ACL_VSTREAM 流在读时调用系统的 read 函数 */ else fdp->stream->read_ready = 1; } /* 检查描述字是否可写 */ if (FD_ISSET(sockfd, &wmask)) { /* 给该描述字对象附加可写属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; } } } TAG_DONE: /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); /* 优先处理定时器中的任务 */ while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { if (timer->when > eventp->present) break; timer_fn = timer->callback; timer_arg = timer->context; /* 如果定时器的时间间隔 > 0 且允许定时器被循环调用, * 则再重设定时器 */ if (timer->delay > 0 && timer->keep) { timer->ncount++; eventp->timer_request(eventp, timer->callback, timer->context, timer->delay, timer->keep); } else { acl_ring_detach(&timer->ring); /* first this */ timer->nrefer--; if (timer->nrefer != 0) acl_msg_fatal("%s(%d): nrefer(%d) != 0", myname, __LINE__, timer->nrefer); acl_myfree(timer); } timer_fn(ACL_EVENT_TIME, eventp, timer_arg); } /* 处理准备好的描述字事件 */ if (eventp->ready_cnt > 0) event_fire(eventp); eventp->nested--; }
static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_POLL *ev = (EVENT_POLL *) eventp; ACL_EVENT_TIMER *timer; int nready, i, revents; acl_int64 delay; ACL_EVENT_FDTABLE *fdp; delay = eventp->delay_sec * 1000000 + eventp->delay_usec; if (delay < DELAY_MIN) delay = DELAY_MIN; /* 调整事件引擎的时间截 */ SET_TIME(eventp->present); /* 根据定时器任务的最近任务计算 poll 的检测超时上限 */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = timer->when - eventp->present; if (n <= 0) delay = 0; else if (n < delay) delay = n; } /* 调用 event_prepare 检查有多少个描述字需要通过 poll 进行检测 */ if (event_prepare(eventp) == 0) { /* 说明无须 poll 检测 */ if (eventp->ready_cnt == 0) /* 为避免循环过快,休眠一下 */ acl_doze(delay > DELAY_MIN ? (int) delay / 1000 : 1); goto TAG_DONE; } /* 如果已经有描述字准备好则 poll 检测超时时间置 0 */ if (eventp->ready_cnt > 0) delay = 0; /* 调用 poll 系统调用检测可用描述字 */ nready = poll(ev->fds, eventp->fdcnt, (int) (delay / 1000)); if (eventp->nested++ > 0) { acl_msg_error("%s(%d): recursive call", myname, __LINE__); exit (1); } if (nready < 0) { if (acl_last_error() != ACL_EINTR) { acl_msg_error("%s(%d), %s: select: %s", __FILE__, __LINE__, myname, acl_last_serror()); exit (1); } goto TAG_DONE; } else if (nready == 0) goto TAG_DONE; /* 检查 poll 的检测结果集合 */ for (i = 0; i < eventp->fdcnt; i++) { fdp = acl_fdmap_ctx(ev->fdmap, ev->fds[i].fd); if (fdp == NULL || fdp->stream == NULL) continue; /* 如果该描述字对象已经在被设置为异常或超时状态则继续 */ if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) continue; revents = ev->fds[i].revents; /* 检查描述字是否出现异常 */ if ((revents & (POLLHUP | POLLERR)) != 0) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; continue; } /* 检查描述字是否可读 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_READ) && (revents & POLLIN) ) { /* 给该描述字对象附加可读属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; } if (fdp->listener) fdp->event_type |= ACL_EVENT_ACCEPT; /* 该描述字可读则设置 ACL_VSTREAM 的系统可读标志从而 * 触发 ACL_VSTREAM 流在读时调用系统的 read 函数 */ else fdp->stream->read_ready = 1; } /* 检查描述字是否可写 */ if ((fdp->flag & EVENT_FDTABLE_FLAG_WRITE) && (revents & POLLOUT)) { /* 给该描述字对象附加可写属性 */ if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->ready_cnt; eventp->ready[eventp->ready_cnt++] = fdp; } } } TAG_DONE: event_timer_trigger(eventp); /* 处理准备好的描述字事件 */ if (eventp->ready_cnt > 0) event_fire(eventp); eventp->nested--; }
int env_set(const wcstring &key, const wchar_t *val, int var_mode) { ASSERT_IS_MAIN_THREAD(); env_node_t *node = NULL; bool has_changed_old = has_changed_exported; bool has_changed_new = false; var_entry_t *e=0; int done=0; int is_universal = 0; if( val && contains( key, L"PWD", L"HOME" ) ) { /* Canoncalize our path; if it changes, recurse and try again. */ wcstring val_canonical = val; path_make_canonical(val_canonical); if (val != val_canonical) { return env_set( key, val_canonical.c_str(), var_mode ); } } if( (var_mode & ENV_USER ) && is_read_only(key) ) { return ENV_PERM; } if (key == L"umask") { wchar_t *end; /* Set the new umask */ if( val && wcslen(val) ) { errno=0; long mask = wcstol( val, &end, 8 ); if( !errno && (!*end) && (mask <= 0777) && (mask >= 0) ) { umask( mask ); } } /* Do not actually create a umask variable, on env_get, it will be calculated dynamically */ return 0; } /* Zero element arrays are internaly not coded as null but as this placeholder string */ if( !val ) { val = ENV_NULL; } if( var_mode & ENV_UNIVERSAL ) { int exportv = 0; if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) { env_universal_get_export( key ); } else { exportv = (var_mode & ENV_EXPORT ); } env_universal_set(key, val, exportv); is_universal = 1; } else { node = env_get_node( key ); if( node ) { var_table_t::iterator result = node->env.find(key); assert(result != node->env.end()); e = result->second; if( e->exportv ) { has_changed_new = true; } } if( (var_mode & ENV_LOCAL) || (var_mode & ENV_GLOBAL) ) { node = ( var_mode & ENV_GLOBAL )?global_env:top; } else { if( node ) { if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) { var_mode = e->exportv?ENV_EXPORT:0; } } else { if( ! get_proc_had_barrier()) { set_proc_had_barrier(true); env_universal_barrier(); } if( env_universal_get( key ) ) { int exportv = 0; if( !(var_mode & ENV_EXPORT ) && !(var_mode & ENV_UNEXPORT ) ) { env_universal_get_export( key ); } else { exportv = (var_mode & ENV_EXPORT ); } env_universal_set(key, val, exportv); is_universal = 1; done = 1; } else { /* New variable with unspecified scope. The default scope is the innermost scope that is shadowing, which will be either the current function or the global scope. */ node = top; while( node->next && !node->new_scope ) { node = node->next; } } } } if( !done ) { var_entry_t *old_entry = NULL; var_table_t::iterator result = node->env.find(key); if ( result != node->env.end() ) { old_entry = result->second; node->env.erase(result); } var_entry_t *entry = NULL; if( old_entry ) { entry = old_entry; if( (var_mode & ENV_EXPORT) || entry->exportv ) { entry->exportv = !!(var_mode & ENV_EXPORT); has_changed_new = true; } } else { entry = new var_entry_t; if( var_mode & ENV_EXPORT) { entry->exportv = 1; has_changed_new = true; } else { entry->exportv = 0; } } entry->val = val; node->env[key] = entry; if( entry->exportv ) { node->exportv=1; } if (has_changed_old || has_changed_new) mark_changed_exported(); } } if( !is_universal ) { event_t ev = event_t::variable_event(key); ev.arguments.reset(new wcstring_list_t); ev.arguments->push_back(L"VARIABLE"); ev.arguments->push_back(L"SET"); ev.arguments->push_back(key); // debug( 1, L"env_set: fire events on variable %ls", key ); event_fire( &ev ); // debug( 1, L"env_set: return from event firing" ); ev.arguments.reset(NULL); } react_to_variable_change(key); return 0; }
static void event_loop(ACL_EVENT *eventp) { const char *myname = "event_loop"; EVENT_KERNEL *ev = (EVENT_KERNEL *) eventp; ACL_EVENT_NOTIFY_TIME timer_fn; void *timer_arg; ACL_EVENT_TIMER *timer; int delay; ACL_EVENT_FDTABLE *fdp; delay = (int) (eventp->delay_sec * 1000 + eventp->delay_usec / 1000); if (delay < 0) delay = 0; /* 0 milliseconds at least */ SET_TIME(eventp->present); /* * Find out when the next timer would go off. Timer requests are sorted. * If any timer is scheduled, adjust the delay appropriately. */ if ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { acl_int64 n = (timer->when - eventp->present) / 1000; if (n <= 0) delay = 0; else if ((int) n < delay) delay = (int) n; } eventp->nested++; event_set_all(eventp); if (eventp->fdcnt == 0) { if (eventp->fdcnt_ready == 0) sleep(1); goto TAG_DONE; } if (eventp->fdcnt_ready > 0) delay = 0; TAG_DONE: /* * Deliver timer events. Requests are sorted: we can stop when we reach * the future or the list end. Allow the application to update the timer * queue while it is being called back. To this end, we repeatedly pop * the first request off the timer queue before delivering the event to * the application. */ SET_TIME(eventp->present); while ((timer = ACL_FIRST_TIMER(&eventp->timer_head)) != 0) { if (timer->when > eventp->present) break; timer_fn = timer->callback; timer_arg = timer->context; /* 如果定时器的时间间隔 > 0 且允许定时器被循环调用,则再重设定时器 */ if (timer->delay > 0 && timer->keep) { timer->ncount++; eventp->timer_request(eventp, timer->callback, timer->context, timer->delay, timer->keep); } else { acl_ring_detach(&timer->ring); /* first this */ timer->nrefer--; if (timer->nrefer != 0) acl_msg_fatal("%s(%d): nrefer(%d) != 0", myname, __LINE__, timer->nrefer); acl_myfree(timer); } timer_fn(ACL_EVENT_TIME, eventp, timer_arg); } for (;;) { BOOL isSuccess = FALSE; DWORD bytesTransferred = 0; DWORD iocpKey = 0; DWORD lastError = 0; IOCP_EVENT *iocp_event = NULL; isSuccess = GetQueuedCompletionStatus(ev->h_iocp, &bytesTransferred, (DWORD*) &fdp, (OVERLAPPED**) &iocp_event, delay); if (!isSuccess) { if (iocp_event == NULL) break; if (iocp_event->type == IOCP_EVENT_DEAD) acl_myfree(iocp_event); else if (iocp_event->fdp == NULL) { acl_msg_warn("%s(%d): fdp null", myname, __LINE__); acl_myfree(iocp_event); } else if (iocp_event->fdp != fdp) acl_msg_fatal("%s(%d): invalid fdp", myname, __LINE__); else if (!(fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) { fdp->event_type |= ACL_EVENT_XCPT; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } continue; } acl_assert(fdp == iocp_event->fdp); if ((fdp->event_type & (ACL_EVENT_XCPT | ACL_EVENT_RW_TIMEOUT))) { continue; } if (iocp_event->type == IOCP_EVENT_READ) { acl_assert(fdp->event_read == iocp_event); iocp_event->type &= ~IOCP_EVENT_READ; fdp->stream->sys_read_ready = 1; if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_READ; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } } if (iocp_event->type == IOCP_EVENT_WRITE) { acl_assert(fdp->event_write == iocp_event); iocp_event->type &= ~IOCP_EVENT_WRITE; if ((fdp->event_type & (ACL_EVENT_READ | ACL_EVENT_WRITE)) == 0) { fdp->event_type |= ACL_EVENT_WRITE; fdp->fdidx_ready = eventp->fdcnt_ready; eventp->fdtabs_ready[eventp->fdcnt_ready] = fdp; eventp->fdcnt_ready++; } } delay = 0; } if (eventp->fdcnt_ready > 0) event_fire(eventp); eventp->nested--; }