コード例 #1
0
ファイル: env.cpp プロジェクト: lnsoso/fish-shell
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;
}
コード例 #2
0
ファイル: threaded_module.c プロジェクト: nu774/libsoxrate
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;
}
コード例 #3
0
ファイル: input.c プロジェクト: cardmagic/lucash
/**
   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;	
}
コード例 #4
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 *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);
}
コード例 #5
0
ファイル: event.cpp プロジェクト: EmuxEvans/fish-shell
/// 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;
}
コード例 #6
0
ファイル: proc.cpp プロジェクト: Sam0523/fish-shell
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);
}
コード例 #7
0
ファイル: env.cpp プロジェクト: octaexon/fish-shell
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;	
}
コード例 #8
0
ファイル: threaded_module.c プロジェクト: nu774/libsoxrate
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;
}
コード例 #9
0
ファイル: env.cpp プロジェクト: octaexon/fish-shell
/**
   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);
}
コード例 #10
0
ファイル: event.c プロジェクト: nocrew/ostis
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;
}
コード例 #11
0
ファイル: events_kernel.c プロジェクト: 10jschen/acl
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--;
}
コード例 #12
0
ファイル: env.cpp プロジェクト: lnsoso/fish-shell
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;
}
コード例 #13
0
ファイル: events_select.c プロジェクト: LazyPlanet/acl
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--;
}
コード例 #14
0
ファイル: events_poll.c プロジェクト: iYefeng/acl
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--;
}
コード例 #15
0
ファイル: env.cpp プロジェクト: octaexon/fish-shell
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;
}
コード例 #16
0
ファイル: events_iocp.c プロジェクト: Tim9Liu9/acl
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--;
}