示例#1
0
/* Iterates over all registered timeouts and determine which
 * will be the first to expire.
 * @timeout: filled with expiry time of soonest timer, or -1 if
 *           no timeout is pending
 * returns: 0 on success, -1 on error
 */
static int virEventPollCalculateTimeout(int *timeout) {
    unsigned long long then = 0;
    int i;
    EVENT_DEBUG("Calculate expiry of %zu timers", eventLoop.timeoutsCount);
    /* Figure out if we need a timeout */
    for (i = 0 ; i < eventLoop.timeoutsCount ; i++) {
        if (eventLoop.timeouts[i].frequency < 0)
            continue;

        EVENT_DEBUG("Got a timeout scheduled for %llu", eventLoop.timeouts[i].expiresAt);
        if (then == 0 ||
            eventLoop.timeouts[i].expiresAt < then)
            then = eventLoop.timeouts[i].expiresAt;
    }

    /* Calculate how long we should wait for a timeout if needed */
    if (then > 0) {
        unsigned long long now;

        if (virTimeMillisNow(&now) < 0)
            return -1;

        *timeout = then - now;
        if (*timeout < 0)
            *timeout = 0;
    } else {
        *timeout = -1;
    }

    EVENT_DEBUG("Timeout at %llu due in %d ms", then, *timeout);

    return 0;
}
示例#2
0
void ewol::context::InputManager::transfertEvent(ewol::WidgetShared _source, ewol::WidgetShared _destination) {
	if(    _source == nullptr
	    || _destination == nullptr) {
		// prevent errors ...
		return;
	}
	for(int32_t iii=0; iii<MAX_MANAGE_INPUT; iii++) {
		ewol::WidgetShared tmpWidget = m_eventInputSaved[iii].curentWidgetEvent.lock();
		if (tmpWidget == _source) {
			// inform the widget that it does not receive the event now
			EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventInputSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_ABORT] " << m_eventInputSaved[iii].posEvent);
			localEventInput(gale::key::type::finger, tmpWidget, m_eventInputSaved[iii].destinationInputId, gale::key::status::abort, m_eventInputSaved[iii].posEvent);
			// set the new widget ...
			m_eventInputSaved[iii].curentWidgetEvent = _destination;
			// inform the widget that he receive the event property now...
			EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventInputSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_TRANSFERT] " << m_eventInputSaved[iii].posEvent);
			localEventInput(gale::key::type::finger, _destination, m_eventInputSaved[iii].destinationInputId, gale::key::status::transfert, m_eventInputSaved[iii].posEvent);
		}
		tmpWidget = m_eventMouseSaved[iii].curentWidgetEvent.lock();
		if (tmpWidget == _source) {
			// inform the widget that it does not receive the event now
			EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventMouseSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_ABORT] " << m_eventMouseSaved[iii].posEvent);
			localEventInput(gale::key::type::mouse, tmpWidget, m_eventMouseSaved[iii].destinationInputId, gale::key::status::abort, m_eventMouseSaved[iii].posEvent);
			// set the new widget ...
			m_eventMouseSaved[iii].curentWidgetEvent = _destination;
			// inform the widget that he receive the event property now...
			EVENT_DEBUG("GUI : Input ID=" << iii << " == >" << m_eventMouseSaved[iii].destinationInputId << " [EVENT_INPUT_TYPE_TRANSFERT] " << m_eventMouseSaved[iii].posEvent);
			localEventInput(gale::key::type::mouse, _destination, m_eventMouseSaved[iii].destinationInputId, gale::key::status::transfert, m_eventMouseSaved[iii].posEvent);
		}
	}
}
示例#3
0
/*
 * Run a single iteration of the event loop, blocking until
 * at least one file handle has an event, or a timer expires
 */
int virEventPollRunOnce(void)
{
    struct pollfd *fds = NULL;
    int ret, timeout, nfds;

    virMutexLock(&eventLoop.lock);
    eventLoop.running = 1;
    virThreadSelf(&eventLoop.leader);

    virEventPollCleanupTimeouts();
    virEventPollCleanupHandles();

    if (!(fds = virEventPollMakePollFDs(&nfds)) ||
        virEventPollCalculateTimeout(&timeout) < 0)
        goto error;

    virMutexUnlock(&eventLoop.lock);

 retry:
    PROBE(EVENT_POLL_RUN,
          "nhandles=%d timeout=%d",
          nfds, timeout);
    ret = poll(fds, nfds, timeout);
    if (ret < 0) {
        EVENT_DEBUG("Poll got error event %d", errno);
        if (errno == EINTR || errno == EAGAIN) {
            goto retry;
        }
        virReportSystemError(errno, "%s",
                             _("Unable to poll on file handles"));
        goto error_unlocked;
    }
    EVENT_DEBUG("Poll got %d event(s)", ret);

    virMutexLock(&eventLoop.lock);
    if (virEventPollDispatchTimeouts() < 0)
        goto error;

    if (ret > 0 &&
        virEventPollDispatchHandles(nfds, fds) < 0)
        goto error;

    virEventPollCleanupTimeouts();
    virEventPollCleanupHandles();

    eventLoop.running = 0;
    virMutexUnlock(&eventLoop.lock);
    VIR_FREE(fds);
    return 0;

 error:
    virMutexUnlock(&eventLoop.lock);
 error_unlocked:
    VIR_FREE(fds);
    return -1;
}
/**********************************************************************
* %FUNCTION: Event_AddHandler
* %ARGUMENTS:
*  es -- event selector
*  fd -- file descriptor to watch
*  flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE
*  fn -- callback function to call when event is triggered
*  data -- extra data to pass to callback function
* %RETURNS:
*  A newly-allocated EventHandler, or NULL.
***********************************************************************/
EventHandler *
Event_AddHandler(EventSelector *es,
		 int fd,
		 unsigned int flags,
		 EventCallbackFunc fn,
		 void *data)
{
    EventHandler *eh;

    /* Specifically disable timer and deleted flags */
    flags &= (~(EVENT_TIMER_BITS | EVENT_FLAG_DELETED));

    /* Bad file descriptor */
    if (fd < 0) {
	errno = EBADF;
	return NULL;
    }

    eh = malloc(sizeof(EventHandler));
    if (!eh) return NULL;
    eh->fd = fd;
    eh->flags = flags;
    eh->tmout.tv_usec = 0;
    eh->tmout.tv_sec = 0;
    eh->fn = fn;
    eh->data = data;

    /* Add immediately.  This is safe even if we are in a handler. */
    eh->next = es->handlers;
    es->handlers = eh;

    EVENT_DEBUG(("Event_AddHandler(es=%p, fd=%d, flags=%u) -> %p\n", es, fd, flags, eh));
    return eh;
}
/**********************************************************************
* %FUNCTION: Event_DelHandler
* %ARGUMENTS:
*  es -- event selector
*  eh -- event handler
* %RETURNS:
*  0 if OK, non-zero if there is an error
* %DESCRIPTION:
*  Deletes the event handler eh
***********************************************************************/
int
Event_DelHandler(EventSelector *es,
		 EventHandler *eh)
{
    /* Scan the handlers list */
    EventHandler *cur, *prev;
    EVENT_DEBUG(("Event_DelHandler(es=%p, eh=%p)\n", es, eh));
    for (cur=es->handlers, prev=NULL; cur; prev=cur, cur=cur->next) {
	if (cur == eh) {
	    if (es->nestLevel) {
		eh->flags |= EVENT_FLAG_DELETED;
		es->opsPending = 1;
		return 0;
	    } else {
		if (prev) prev->next = cur->next;
		else      es->handlers = cur->next;

		DestroyHandler(cur);
		return 0;
	    }
	}
    }

    /* Handler not found */
    return 1;
}
示例#6
0
/*
 * Unregister a callback from a file handle
 * NB, it *must* be safe to call this from within a callback
 * For this reason we only ever set a flag in the existing list.
 * Actual deletion will be done out-of-band
 */
int virEventPollRemoveHandle(int watch) {
    int i;
    PROBE(EVENT_POLL_REMOVE_HANDLE,
          "watch=%d",
          watch);

    if (watch <= 0) {
        VIR_WARN("Ignoring invalid remove watch %d", watch);
        return -1;
    }

    virMutexLock(&eventLoop.lock);
    for (i = 0 ; i < eventLoop.handlesCount ; i++) {
        if (eventLoop.handles[i].deleted)
            continue;

        if (eventLoop.handles[i].watch == watch) {
            EVENT_DEBUG("mark delete %d %d", i, eventLoop.handles[i].fd);
            eventLoop.handles[i].deleted = 1;
            virEventPollInterruptLocked();
            virMutexUnlock(&eventLoop.lock);
            return 0;
        }
    }
    virMutexUnlock(&eventLoop.lock);
    return -1;
}
示例#7
0
/*
 * Allocate a pollfd array containing data for all registered
 * file handles. The caller must free the returned data struct
 * returns: the pollfd array, or NULL on error
 */
static struct pollfd *virEventPollMakePollFDs(int *nfds) {
    struct pollfd *fds;
    int i;

    *nfds = 0;
    for (i = 0 ; i < eventLoop.handlesCount ; i++) {
        if (eventLoop.handles[i].events && !eventLoop.handles[i].deleted)
            (*nfds)++;
    }

    /* Setup the poll file handle data structs */
    if (VIR_ALLOC_N(fds, *nfds) < 0) {
        virReportOOMError();
        return NULL;
    }

    *nfds = 0;
    for (i = 0 ; i < eventLoop.handlesCount ; i++) {
        EVENT_DEBUG("Prepare n=%d w=%d, f=%d e=%d d=%d", i,
                    eventLoop.handles[i].watch,
                    eventLoop.handles[i].fd,
                    eventLoop.handles[i].events,
                    eventLoop.handles[i].deleted);
        if (!eventLoop.handles[i].events || eventLoop.handles[i].deleted)
            continue;
        fds[*nfds].fd = eventLoop.handles[i].fd;
        fds[*nfds].events = eventLoop.handles[i].events;
        fds[*nfds].revents = 0;
        (*nfds)++;
        //EVENT_DEBUG("Wait for %d %d", eventLoop.handles[i].fd, eventLoop.handles[i].events);
    }

    return fds;
}
/**********************************************************************
* %FUNCTION: Event_AddHandlerWithTimeout
* %ARGUMENTS:
*  es -- event selector
*  fd -- file descriptor to watch
*  flags -- combination of EVENT_FLAG_READABLE and EVENT_FLAG_WRITEABLE
*  t -- Timeout after which to call handler, even if not readable/writable.
*       If t.tv_sec < 0, calls normal Event_AddHandler with no timeout.
*  fn -- callback function to call when event is triggered
*  data -- extra data to pass to callback function
* %RETURNS:
*  A newly-allocated EventHandler, or NULL.
***********************************************************************/
EventHandler *
Event_AddHandlerWithTimeout(EventSelector *es,
			    int fd,
			    unsigned int flags,
			    struct timeval t,
			    EventCallbackFunc fn,
			    void *data)
{
    EventHandler *eh;
    struct timeval now;

    /* If timeout is negative, just do normal non-timing-out event */
    if (t.tv_sec < 0 || t.tv_usec < 0) {
	return Event_AddHandler(es, fd, flags, fn, data);
    }

    /* Specifically disable timer and deleted flags */
    flags &= (~(EVENT_FLAG_TIMER | EVENT_FLAG_DELETED));
    flags |= EVENT_FLAG_TIMEOUT;

    /* Bad file descriptor? */
    if (fd < 0) {
	errno = EBADF;
	return NULL;
    }

    /* Bad timeout? */
    if (t.tv_usec >= 1000000) {
	errno = EINVAL;
	return NULL;
    }

    eh = malloc(sizeof(EventHandler));
    if (!eh) return NULL;

    /* Convert time interval to absolute time */
    gettimeofday(&now, NULL);

    t.tv_sec += now.tv_sec;
    t.tv_usec += now.tv_usec;
    if (t.tv_usec >= 1000000) {
	t.tv_usec -= 1000000;
	t.tv_sec++;
    }

    eh->fd = fd;
    eh->flags = flags;
    eh->tmout = t;
    eh->fn = fn;
    eh->data = data;

    /* Add immediately.  This is safe even if we are in a handler. */
    eh->next = es->handlers;
    es->handlers = eh;

    EVENT_DEBUG(("Event_AddHandlerWithTimeout(es=%p, fd=%d, flags=%u, t=%d/%d) -> %p\n", es, fd, flags, t.tv_sec, t.tv_usec, eh));
    return eh;
}
示例#9
0
/**********************************************************************
* %FUNCTION: free_state
* %ARGUMENTS:
*  state -- EventTcpState to free
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Frees all state associated with the TcpEvent.
***********************************************************************/
static void
free_state(EventTcpState *state)
{
    if (!state) return;
    EVENT_DEBUG(("tcp_free_state(state=%p)\n", state));
    if (state->buf) free(state->buf);
    if (state->eh) Event_DelHandler(state->es, state->eh);
    free(state);
}
示例#10
0
/**********************************************************************
* %FUNCTION: handle_writeable
* %ARGUMENTS:
*  es -- event selector
*  fd -- the writeable socket
*  flags -- ignored
*  data -- the EventTcpState object
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Continues to fill buffer.  Calls callback when done.
***********************************************************************/
static void
handle_writeable(EventSelector *es,
		int fd,
		unsigned int flags,
		void *data)
{
    EventTcpState *state = (EventTcpState *) data;
    int done = state->cur - state->buf;
    int togo = state->len - done;
    int n;

    /* Timed out? */
    if (flags & EVENT_FLAG_TIMEOUT) {
	errno = ETIMEDOUT;
	if (state->f) {
	    (state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_TIMEOUT,
		       state->data);
	} else {
	    close(fd);
	}
	free_state(state);
	return;
    }

    /* togo had better not be zero here! */
    n = write(fd, state->cur, togo);

    EVENT_DEBUG(("tcp_handle_writeable(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data));
    if (n <= 0) {
	/* error */
	if (state->f) {
	    (state->f)(es, state->socket, state->buf, done,
		       EVENT_TCP_FLAG_IOERROR,
		       state->data);
	} else {
	    close(fd);
	}
	free_state(state);
	return;
    }
    state->cur += n;
    done += n;
    if (done >= state->len) {
	/* Written enough! */
	if (state->f) {
	    (state->f)(es, state->socket, state->buf, done,
		       EVENT_TCP_FLAG_COMPLETE, state->data);
	} else {
	    close(fd);
	}
	free_state(state);
	return;
    }

}
/**********************************************************************
* %FUNCTION: Event_CreateSelector
* %ARGUMENTS:
*  None
* %RETURNS:
*  A newly-allocated EventSelector, or NULL if out of memory.
* %DESCRIPTION:
*  Creates a new EventSelector.
***********************************************************************/
EventSelector *
Event_CreateSelector(void)
{
    EventSelector *es = malloc(sizeof(EventSelector));
    if (!es) return NULL;
    es->handlers = NULL;
    es->nestLevel = 0;
    es->destroyPending = 0;
    es->opsPending = 0;
    EVENT_DEBUG(("CreateSelector() -> %p\n", (void *) es));
    return es;
}
示例#12
0
/**********************************************************************
* %FUNCTION: handle_accept
* %ARGUMENTS:
*  es -- event selector
*  fd -- socket
*  flags -- ignored
*  data -- the accept callback function
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Calls accept; if a connection arrives, calls the accept callback
*  function with connected descriptor
***********************************************************************/
static void
handle_accept(EventSelector *es,
	      int fd,
	      unsigned int flags,
	      void *data)
{
    int conn;
    EventTcpAcceptFunc f;

    EVENT_DEBUG(("tcp_handle_accept(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data));
    conn = accept(fd, NULL, NULL);
    if (conn < 0) return;
    f = (EventTcpAcceptFunc) data;

    f(es, conn);
}
示例#13
0
/* Used post dispatch to actually remove any handles that
 * were previously marked as deleted. This asynchronous
 * cleanup is needed to make dispatch re-entrant safe.
 */
static void virEventPollCleanupHandles(void)
{
    size_t i;
    size_t gap;
    VIR_DEBUG("Cleanup %zu", eventLoop.handlesCount);

    /* Remove deleted entries, shuffling down remaining
     * entries as needed to form contiguous series
     */
    for (i = 0; i < eventLoop.handlesCount;) {
        if (!eventLoop.handles[i].deleted) {
            i++;
            continue;
        }

        PROBE(EVENT_POLL_PURGE_HANDLE,
              "watch=%d",
              eventLoop.handles[i].watch);
        if (eventLoop.handles[i].ff) {
            virFreeCallback ff = eventLoop.handles[i].ff;
            void *opaque = eventLoop.handles[i].opaque;
            virMutexUnlock(&eventLoop.lock);
            ff(opaque);
            virMutexLock(&eventLoop.lock);
        }

        if ((i+1) < eventLoop.handlesCount) {
            memmove(eventLoop.handles+i,
                    eventLoop.handles+i+1,
                    sizeof(struct virEventPollHandle)*(eventLoop.handlesCount
                                                   -(i+1)));
        }
        eventLoop.handlesCount--;
    }

    /* Release some memory if we've got a big chunk free */
    gap = eventLoop.handlesAlloc - eventLoop.handlesCount;
    if (eventLoop.handlesCount == 0 ||
        (gap > eventLoop.handlesCount && gap > EVENT_ALLOC_EXTENT)) {
        EVENT_DEBUG("Found %zu out of %zu handles slots used, releasing %zu",
                    eventLoop.handlesCount, eventLoop.handlesAlloc, gap);
        VIR_SHRINK_N(eventLoop.handles, eventLoop.handlesAlloc, gap);
    }
}
示例#14
0
/*
 * Register a callback for a timer event
 * NB, it *must* be safe to call this from within a callback
 * For this reason we only ever append to existing list.
 */
int virEventPollAddTimeout(int frequency,
                           virEventTimeoutCallback cb,
                           void *opaque,
                           virFreeCallback ff)
{
    unsigned long long now;
    int ret;

    if (virTimeMillisNow(&now) < 0) {
        return -1;
    }

    virMutexLock(&eventLoop.lock);
    if (eventLoop.timeoutsCount == eventLoop.timeoutsAlloc) {
        EVENT_DEBUG("Used %zu timeout slots, adding at least %d more",
                    eventLoop.timeoutsAlloc, EVENT_ALLOC_EXTENT);
        if (VIR_RESIZE_N(eventLoop.timeouts, eventLoop.timeoutsAlloc,
                         eventLoop.timeoutsCount, EVENT_ALLOC_EXTENT) < 0) {
            virMutexUnlock(&eventLoop.lock);
            return -1;
        }
    }

    eventLoop.timeouts[eventLoop.timeoutsCount].timer = nextTimer++;
    eventLoop.timeouts[eventLoop.timeoutsCount].frequency = frequency;
    eventLoop.timeouts[eventLoop.timeoutsCount].cb = cb;
    eventLoop.timeouts[eventLoop.timeoutsCount].ff = ff;
    eventLoop.timeouts[eventLoop.timeoutsCount].opaque = opaque;
    eventLoop.timeouts[eventLoop.timeoutsCount].deleted = 0;
    eventLoop.timeouts[eventLoop.timeoutsCount].expiresAt =
        frequency >= 0 ? frequency + now : 0;

    eventLoop.timeoutsCount++;
    ret = nextTimer-1;
    virEventPollInterruptLocked();

    PROBE(EVENT_POLL_ADD_TIMEOUT,
          "timer=%d frequency=%d cb=%p opaque=%p ff=%p",
          ret, frequency, cb, opaque, ff);
    virMutexUnlock(&eventLoop.lock);
    return ret;
}
/**********************************************************************
* %FUNCTION: Event_AddTimerHandler
* %ARGUMENTS:
*  es -- event selector
*  t -- time interval after which to trigger event
*  fn -- callback function to call when event is triggered
*  data -- extra data to pass to callback function
* %RETURNS:
*  A newly-allocated EventHandler, or NULL.
***********************************************************************/
EventHandler *
Event_AddTimerHandler(EventSelector *es,
		      struct timeval t,
		      EventCallbackFunc fn,
		      void *data)
{
    EventHandler *eh;
    struct timeval now;

    /* Check time interval for validity */
    if (t.tv_sec < 0 || t.tv_usec < 0 || t.tv_usec >= 1000000) {
	errno = EINVAL;
	return NULL;
    }

    eh = malloc(sizeof(EventHandler));
    if (!eh) return NULL;

    /* Convert time interval to absolute time */
    gettimeofday(&now, NULL);

    t.tv_sec += now.tv_sec;
    t.tv_usec += now.tv_usec;
    if (t.tv_usec >= 1000000) {
	t.tv_usec -= 1000000;
	t.tv_sec++;
    }

    eh->fd = -1;
    eh->flags = EVENT_FLAG_TIMER;
    eh->tmout = t;
    eh->fn = fn;
    eh->data = data;

    /* Add immediately.  This is safe even if we are in a handler. */
    eh->next = es->handlers;
    es->handlers = eh;

    EVENT_DEBUG(("Event_AddTimerHandler(es=%p, t=%d/%d) -> %p\n", es, t.tv_sec,t.tv_usec, eh));
    return eh;
}
示例#16
0
/**********************************************************************
* %FUNCTION: handle_connect
* %ARGUMENTS:
*  es -- event selector
*  fd -- socket
*  flags -- ignored
*  data -- the accept callback function
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Calls accept; if a connection arrives, calls the accept callback
*  function with connected descriptor
***********************************************************************/
static void
handle_connect(EventSelector *es,
	      int fd,
	      unsigned int flags,
	      void *data)
{
    int error = 0;
    socklen_t len = sizeof(error);
    EventTcpConnectState *state = (EventTcpConnectState *) data;

    EVENT_DEBUG(("tcp_handle_connect(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data));

    /* Cancel writable event */
    Event_DelHandler(es, state->conn);
    state->conn = NULL;

    /* Timeout? */
    if (flags & EVENT_FLAG_TIMEOUT) {
	errno = ETIMEDOUT;
	state->f(es, fd, EVENT_TCP_FLAG_TIMEOUT, state->data);
	free(state);
	return;
    }

    /* Check for pending error */
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
	state->f(es, fd, EVENT_TCP_FLAG_IOERROR, state->data);
	free(state);
	return;
    }
    if (error) {
	errno = error;
	state->f(es, fd, EVENT_TCP_FLAG_IOERROR, state->data);
	free(state);
	return;
    }

    /* It looks cool! */
    state->f(es, fd, EVENT_TCP_FLAG_COMPLETE, state->data);
    free(state);
}
示例#17
0
/**********************************************************************
* %FUNCTION: EventTcp_CreateAcceptor
* %ARGUMENTS:
*  es -- event selector
*  socket -- listening socket
*  f -- function to call when a connection is accepted
*  data -- extra data to pass to f.
* %RETURNS:
*  An event handler on success, NULL on failure.
* %DESCRIPTION:
*  Sets up an accepting socket and calls "f" whenever a new
*  connection arrives.
***********************************************************************/
EventHandler *
EventTcp_CreateAcceptor(EventSelector *es,
			int socket,
			EventTcpAcceptFunc f)
{
    int flags;

    EVENT_DEBUG(("EventTcp_CreateAcceptor(es=%p, socket=%d)\n", es, socket));
    /* Make sure socket is non-blocking */
    flags = fcntl(socket, F_GETFL, 0);
    if (flags == -1) {
	return NULL;
    }
    if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) {
	return NULL;
    }

    return Event_AddHandler(es, socket, EVENT_FLAG_READABLE,
			    handle_accept, (void *) f);

}
示例#18
0
/* Iterate over all file handles and dispatch any which
 * have pending events listed in the poll() data. Invoke
 * the user supplied callback for each handle which has
 * pending events
 *
 * This method must cope with new handles being registered
 * by a callback, and must skip any handles marked as deleted.
 *
 * Returns 0 upon success, -1 if an error occurred
 */
static int virEventPollDispatchHandles(int nfds, struct pollfd *fds)
{
    size_t i, n;
    VIR_DEBUG("Dispatch %d", nfds);

    /* NB, use nfds not eventLoop.handlesCount, because new
     * fds might be added on end of list, and they're not
     * in the fds array we've got */
    for (i = 0, n = 0; n < nfds && i < eventLoop.handlesCount; n++) {
        while (i < eventLoop.handlesCount &&
               (eventLoop.handles[i].fd != fds[n].fd ||
                eventLoop.handles[i].events == 0)) {
            i++;
        }
        if (i == eventLoop.handlesCount)
            break;

        VIR_DEBUG("i=%zu w=%d", i, eventLoop.handles[i].watch);
        if (eventLoop.handles[i].deleted) {
            EVENT_DEBUG("Skip deleted n=%zu w=%d f=%d", i,
                        eventLoop.handles[i].watch, eventLoop.handles[i].fd);
            continue;
        }

        if (fds[n].revents) {
            virEventHandleCallback cb = eventLoop.handles[i].cb;
            int watch = eventLoop.handles[i].watch;
            void *opaque = eventLoop.handles[i].opaque;
            int hEvents = virEventPollFromNativeEvents(fds[n].revents);
            PROBE(EVENT_POLL_DISPATCH_HANDLE,
                  "watch=%d events=%d",
                  watch, hEvents);
            virMutexUnlock(&eventLoop.lock);
            (cb)(watch, fds[n].fd, hEvents, opaque);
            virMutexLock(&eventLoop.lock);
        }
    }

    return 0;
}
示例#19
0
/*
 * Register a callback for monitoring file handle events.
 * NB, it *must* be safe to call this from within a callback
 * For this reason we only ever append to existing list.
 */
int virEventPollAddHandle(int fd, int events,
                          virEventHandleCallback cb,
                          void *opaque,
                          virFreeCallback ff)
{
    int watch;
    virMutexLock(&eventLoop.lock);
    if (eventLoop.handlesCount == eventLoop.handlesAlloc) {
        EVENT_DEBUG("Used %zu handle slots, adding at least %d more",
                    eventLoop.handlesAlloc, EVENT_ALLOC_EXTENT);
        if (VIR_RESIZE_N(eventLoop.handles, eventLoop.handlesAlloc,
                         eventLoop.handlesCount, EVENT_ALLOC_EXTENT) < 0) {
            virMutexUnlock(&eventLoop.lock);
            return -1;
        }
    }

    watch = nextWatch++;

    eventLoop.handles[eventLoop.handlesCount].watch = watch;
    eventLoop.handles[eventLoop.handlesCount].fd = fd;
    eventLoop.handles[eventLoop.handlesCount].events =
                                         virEventPollToNativeEvents(events);
    eventLoop.handles[eventLoop.handlesCount].cb = cb;
    eventLoop.handles[eventLoop.handlesCount].ff = ff;
    eventLoop.handles[eventLoop.handlesCount].opaque = opaque;
    eventLoop.handles[eventLoop.handlesCount].deleted = 0;

    eventLoop.handlesCount++;

    virEventPollInterruptLocked();

    PROBE(EVENT_POLL_ADD_HANDLE,
          "watch=%d fd=%d events=%d cb=%p opaque=%p ff=%p",
          watch, fd, events, cb, opaque, ff);
    virMutexUnlock(&eventLoop.lock);

    return watch;
}
示例#20
0
// note if id<0  == > the it was finger event ...
void gale::context::InputManager::motion(enum gale::key::type _type,
                                         int _pointerID,
                                         vec2 _pos) {
	EVENT_DEBUG("motion event : " << _type << " " << _pointerID << " " << _pos);
	if (MAX_MANAGE_INPUT <= _pointerID) {
		// reject pointer  == > out of IDs...
		return;
	}
	InputPoperty *eventTable = nullptr;
	if (_type == gale::key::typeMouse) {
		eventTable = m_eventMouseSaved;
	} else if (_type == gale::key::typeFinger) {
		eventTable = m_eventInputSaved;
	} else {
		GALE_ERROR("Unknown type of event");
		return;
	}
	if(    _pointerID > MAX_MANAGE_INPUT
	    || _pointerID < 0) {
		// not manage input
		return;
	}
	ememory::SharedPtr<gale::Application::Windows> tmpWindows = m_context.getWindows();
	// special case for the mouse event 0 that represent the hover event of the system :
	if (_type == gale::key::typeMouse && _pointerID == 0) {
		// this event is all time on the good Application ... and manage the enter and leave ...
		// NOTE : the "layer Application" force us to get the Application at the specific position all the time :
		ememory::SharedPtr<gale::Application> tmpApplication;
		if (m_grabApplication.lock() != nullptr) {
			// grab all events ...
			tmpApplication = m_grabApplication.lock();
		} else {
			if (nullptr != tmpWindows) {
				tmpApplication = tmpWindows->getApplicationAtPos(_pos);
			}
		}
		if(    tmpApplication != eventTable[_pointerID].curentApplicationEvent.lock()
		    || (    true == eventTable[_pointerID].isInside
		         && (     eventTable[_pointerID].origin.x() > _pos.x()
		              ||  eventTable[_pointerID].origin.y() > _pos.y()
		              || (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x()
		              || (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()) ) ) {
			eventTable[_pointerID].isInside = false;
			EVENT_DEBUG("GUI : Input ID=" << _pointerID << " == >" << eventTable[_pointerID].destinationInputId << " [LEAVE] " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                eventTable[_pointerID].curentApplicationEvent.lock(),
			                eventTable[_pointerID].destinationInputId,
			                gale::key::statusLeave,
			                _pos);
		}
		if (eventTable[_pointerID].isInside == false) {
			// set the element inside ...
			eventTable[_pointerID].isInside = true;
			// get destination Application :
			eventTable[_pointerID].curentApplicationEvent = tmpApplication;
			if (tmpApplication == nullptr) {
				eventTable[_pointerID].isInside = false;
			} else {
				eventTable[_pointerID].origin = tmpApplication->getOrigin();
				eventTable[_pointerID].size = tmpApplication->getSize();
			}
			eventTable[_pointerID].destinationInputId = 0;
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [ENTER] " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                tmpApplication,
			                eventTable[_pointerID].destinationInputId,
			                gale::key::statusEnter,
			                _pos);
		}
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		            << " == >" << eventTable[_pointerID].destinationInputId
		            << " [MOVE]  " << _pos);
		eventTable[_pointerID].posEvent = _pos;
		localEventInput(_type,
		                tmpApplication,
		                eventTable[_pointerID].destinationInputId,
		                gale::key::statusMove,
		                _pos);
	} else if (true == eventTable[_pointerID].isUsed) {
		if (true == eventTable[_pointerID].isInside) {
			if(     eventTable[_pointerID].origin.x() > _pos.x()
			    ||  eventTable[_pointerID].origin.y() > _pos.y()
			    || (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) < _pos.x()
			    || (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) < _pos.y()) {
				eventTable[_pointerID].isInside = false;
				EVENT_DEBUG("GUI : Input ID=" << _pointerID
				            << " == >" << eventTable[_pointerID].destinationInputId
				            << " [LEAVE] " << _pos);
				eventTable[_pointerID].posEvent = _pos;
				localEventInput(_type,
				                eventTable[_pointerID].curentApplicationEvent.lock(),
				                eventTable[_pointerID].destinationInputId,
				                gale::key::statusLeave,
				                _pos);
			}
		} else {
			if(    (     eventTable[_pointerID].origin.x() <= _pos.x()
			         && (eventTable[_pointerID].origin.x() + eventTable[_pointerID].size.x()) >= _pos.x() )
			    && (     eventTable[_pointerID].origin.y() <= _pos.y()
			         && (eventTable[_pointerID].origin.y() + eventTable[_pointerID].size.y()) >= _pos.y() ) ) {
				eventTable[_pointerID].isInside = true;
				EVENT_DEBUG("GUI : Input ID=" << _pointerID
				            << " == >" << eventTable[_pointerID].destinationInputId
				            << " [ENTER] " << _pos);
				eventTable[_pointerID].posEvent = _pos;
				localEventInput(_type,
				                eventTable[_pointerID].curentApplicationEvent.lock(),
				                eventTable[_pointerID].destinationInputId,
				                gale::key::statusEnter,
				                _pos);
			}
		}
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		            << " == >" << eventTable[_pointerID].destinationInputId
		            << " [MOVE]  " << _pos);
		eventTable[_pointerID].posEvent = _pos;
		localEventInput(_type,
		                eventTable[_pointerID].curentApplicationEvent.lock(),
		                eventTable[_pointerID].destinationInputId,
		                gale::key::statusMove,
		                _pos);
	}
}
/**********************************************************************
* %FUNCTION: Event_HandleEvent
* %ARGUMENTS:
*  es -- EventSelector
* %RETURNS:
*  0 if OK, non-zero on error.  errno is set appropriately.
* %DESCRIPTION:
*  Handles a single event (uses select() to wait for an event.)
***********************************************************************/
int
Event_HandleEvent(EventSelector *es)
{
    fd_set readfds, writefds;
    fd_set *rd, *wr;
    unsigned int flags;

    struct timeval abs_timeout = {}, now;
    struct timeval timeout;
    struct timeval *tm;
    EventHandler *eh;

    int r = 0;
    int errno_save = 0;
    int foundTimeoutEvent = 0;
    int foundReadEvent = 0;
    int foundWriteEvent = 0;
    int maxfd = -1;
    int pastDue;

    EVENT_DEBUG(("Enter Event_HandleEvent(es=%p)\n", (void *) es));

    /* Build the select sets */
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);

    eh = es->handlers;
    for (eh=es->handlers; eh; eh=eh->next) {
	if (eh->flags & EVENT_FLAG_DELETED) continue;
	if (eh->flags & EVENT_FLAG_READABLE) {
	    foundReadEvent = 1;
	    FD_SET(eh->fd, &readfds);
	    if (eh->fd > maxfd) maxfd = eh->fd;
	}
	if (eh->flags & EVENT_FLAG_WRITEABLE) {
	    foundWriteEvent = 1;
	    FD_SET(eh->fd, &writefds);
	    if (eh->fd > maxfd) maxfd = eh->fd;
	}
	if (eh->flags & EVENT_TIMER_BITS) {
	    if (!foundTimeoutEvent) {
		abs_timeout = eh->tmout;
		foundTimeoutEvent = 1;
	    } else {
		if (eh->tmout.tv_sec < abs_timeout.tv_sec ||
		    (eh->tmout.tv_sec == abs_timeout.tv_sec &&
		     eh->tmout.tv_usec < abs_timeout.tv_usec)) {
		    abs_timeout = eh->tmout;
		}
	    }
	}
    }
    if (foundReadEvent) {
	rd = &readfds;
    } else {
	rd = NULL;
    }
    if (foundWriteEvent) {
	wr = &writefds;
    } else {
	wr = NULL;
    }

    if (foundTimeoutEvent) {
	gettimeofday(&now, NULL);
	/* Convert absolute timeout to relative timeout for select */
	timeout.tv_usec = abs_timeout.tv_usec - now.tv_usec;
	timeout.tv_sec = abs_timeout.tv_sec - now.tv_sec;
	if (timeout.tv_usec < 0) {
	    timeout.tv_usec += 1000000;
	    timeout.tv_sec--;
	}
	if (timeout.tv_sec < 0 ||
	    (timeout.tv_sec == 0 && timeout.tv_usec < 0)) {
	    timeout.tv_sec = 0;
	    timeout.tv_usec = 0;
	}
	tm = &timeout;
    } else {
	tm = NULL;
    }

    if (foundReadEvent || foundWriteEvent || foundTimeoutEvent) {
	for(;;) {
	    r = select(maxfd+1, rd, wr, NULL, tm);
	    if (r < 0) {
		if (errno == EINTR) continue;
	    }
	    break;
	}
    }

    if (foundTimeoutEvent) gettimeofday(&now, NULL);
    errno_save = errno;
    es->nestLevel++;

    if (r >= 0) {
	/* Call handlers */
	for (eh=es->handlers; eh; eh=eh->next) {

	    /* Pending delete for this handler?  Ignore it */
	    if (eh->flags & EVENT_FLAG_DELETED) continue;

	    flags = 0;
	    if ((eh->flags & EVENT_FLAG_READABLE) &&
		FD_ISSET(eh->fd, &readfds)) {
		flags |= EVENT_FLAG_READABLE;
	    }
	    if ((eh->flags & EVENT_FLAG_WRITEABLE) &&
		FD_ISSET(eh->fd, &writefds)) {
		flags |= EVENT_FLAG_WRITEABLE;
	    }
	    if (eh->flags & EVENT_TIMER_BITS) {
		pastDue = (eh->tmout.tv_sec < now.tv_sec ||
			   (eh->tmout.tv_sec == now.tv_sec &&
			    eh->tmout.tv_usec <= now.tv_usec));
		if (pastDue) {
		    flags |= EVENT_TIMER_BITS;
		    if (eh->flags & EVENT_FLAG_TIMER) {
			/* Timer events are only called once */
			es->opsPending = 1;
			eh->flags |= EVENT_FLAG_DELETED;
		    }
		}
	    }
	    /* Do callback */
	    if (flags) {
		EVENT_DEBUG(("Enter callback: eh=%p flags=%u\n", eh, flags));
		eh->fn(es, eh->fd, flags, eh->data);
		EVENT_DEBUG(("Leave callback: eh=%p flags=%u\n", eh, flags));
	    }
	}
    }

    es->nestLevel--;

    if (!es->nestLevel && es->opsPending) {
	DoPendingChanges(es);
    }
    errno = errno_save;
    return r;
}
/**********************************************************************
* %FUNCTION: DestroyHandler
* %ARGUMENTS:
*  eh -- an event handler
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Destroys handler
***********************************************************************/
void
DestroyHandler(EventHandler *eh)
{
    EVENT_DEBUG(("DestroyHandler(eh=%p)\n", eh));
    free(eh);
}
示例#23
0
void gale::context::InputManager::state(enum gale::key::type _type,
                                        int _pointerID,
                                        bool _isDown,
                                        vec2 _pos)
{
	if (MAX_MANAGE_INPUT <= _pointerID) {
		// reject pointer  == > out of IDs...
		return;
	}
	EVENT_DEBUG("event pointerId=" << _pointerID);
	// convert position in open-GL coordonates ...
	InputPoperty *eventTable = nullptr;
	InputLimit   localLimit;
	if (_type == gale::key::typeMouse) {
		eventTable = m_eventMouseSaved;
		localLimit = m_eventMouseLimit;
	} else if (_type == gale::key::typeFinger) {
		eventTable = m_eventInputSaved;
		localLimit = m_eventInputLimit;
	} else {
		GALE_ERROR("Unknown type of event");
		return;
	}
	if(    _pointerID > MAX_MANAGE_INPUT
	    || _pointerID <= 0) {
		// not manage input
		return;
	}
	// get the curent time ...
	int64_t currentTime = gale::getTime();
	ememory::SharedPtr<gale::Application::Windows> tmpWindows = m_context.getWindows();
	
	if (true == _isDown) {
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		             << " == >" << eventTable[_pointerID].destinationInputId
		             << " [DOWN] " << _pos);
		if(true == eventTable[_pointerID].isUsed) {
			// we have an event previously ... check delay between click and offset position
			if (currentTime - eventTable[_pointerID].lastTimeEvent > localLimit.sepatateTime) {
				cleanElement(eventTable, _pointerID);
			} else if(    abs(eventTable[_pointerID].downStart.x() - _pos.x()) >= localLimit.DpiOffset
			           || abs(eventTable[_pointerID].downStart.y() - _pos.y()) >= localLimit.DpiOffset ){
				cleanElement(eventTable, _pointerID);
			}
		}
		if(true == eventTable[_pointerID].isUsed) {
			// save start time
			eventTable[_pointerID].lastTimeEvent = currentTime;
			// generate DOWN Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [DOWN]   " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                eventTable[_pointerID].curentApplicationEvent.lock(),
			                eventTable[_pointerID].destinationInputId,
			                gale::key::statusDown,
			                _pos);
		} else {
			// Mark it used :
			eventTable[_pointerID].isUsed = true;
			// Save current position :
			eventTable[_pointerID].downStart = _pos;
			// save start time
			eventTable[_pointerID].lastTimeEvent = currentTime;
			// set the element inside ...
			eventTable[_pointerID].isInside = true;
			ememory::SharedPtr<gale::Application> tmpApplication = m_grabApplication.lock();
			// get destination Application :
			if(nullptr != tmpWindows) {
				if (    tmpApplication != nullptr
				     && _type == gale::key::typeMouse) {
					eventTable[_pointerID].curentApplicationEvent = tmpApplication;
				} else {
					eventTable[_pointerID].curentApplicationEvent = tmpWindows->getApplicationAtPos(_pos);
				}
			} else {
				eventTable[_pointerID].curentApplicationEvent.reset();
			}
			tmpApplication = eventTable[_pointerID].curentApplicationEvent.lock();
			if (tmpApplication != nullptr) {
				eventTable[_pointerID].origin = tmpApplication->getOrigin();
				eventTable[_pointerID].size = tmpApplication->getSize();
				eventTable[_pointerID].destinationInputId = localGetDestinationId(_type, tmpApplication, _pointerID);
			} else {
				eventTable[_pointerID].destinationInputId = -1;
			}
			// generate DOWN Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [DOWN]   " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                tmpApplication,
			                eventTable[_pointerID].destinationInputId,
			                gale::key::statusDown,
			                _pos);
		}
	} else {
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		             << " == >" << eventTable[_pointerID].destinationInputId
		             << " [UP]     " << _pos);
		if(false == eventTable[_pointerID].isUsed) {
			// bad case ... ???
			GALE_DEBUG("Up event without previous down ... ");
			// Mark it un-used :
			eventTable[_pointerID].isUsed = false;
			// revove the Application ...
			eventTable[_pointerID].curentApplicationEvent.reset();
		} else {
			ememory::SharedPtr<gale::Application> tmpApplication = eventTable[_pointerID].curentApplicationEvent.lock();
			// generate UP Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [UP]     " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			// send up event after the single event to prevent multiple Application getting elements
			localEventInput(_type,
			                tmpApplication,
			                _pointerID,
			                gale::key::statusUp,
			                _pos);
			// generate event (single)
			if(    abs(eventTable[_pointerID].downStart.x() - _pos.x()) < localLimit.DpiOffset
			    && abs(eventTable[_pointerID].downStart.y() - _pos.y()) < localLimit.DpiOffset ){
				// Save current position :
				eventTable[_pointerID].downStart = _pos;
				// save start time
				eventTable[_pointerID].lastTimeEvent = currentTime;
				int32_t nbClickMax = 0;
				if(tmpApplication != nullptr) {
					nbClickMax = tmpApplication->getMouseLimit();
					if (nbClickMax>5) {
						nbClickMax = 5;
					}
				}
				// in grab mode the single to quinte event are not generated ....
				if(    (    m_grabApplication.lock() == nullptr
				         || _type != gale::key::typeMouse )
				    && eventTable[_pointerID].nbClickEvent < nbClickMax) {
					// generate event SINGLE :
					eventTable[_pointerID].nbClickEvent++;
					EVENT_DEBUG("GUI : Input ID=" << _pointerID
					            << " == >" << eventTable[_pointerID].destinationInputId
					            << " [" << eventTable[_pointerID].nbClickEvent << "] " << _pos);
					eventTable[_pointerID].posEvent = _pos;
					localEventInput(_type,
					                tmpApplication,
					                eventTable[_pointerID].destinationInputId,
					                (enum gale::key::status)(gale::key::statusSingle + eventTable[_pointerID].nbClickEvent-1),
					                _pos);
					if( eventTable[_pointerID].nbClickEvent >= nbClickMax) {
						eventTable[_pointerID].nbClickEvent = 0;
					}
				} else {
					eventTable[_pointerID].nbClickEvent = 0;
				}
			}
			// send up event after the single event to prevent multiple Application getting elements
			localEventInput(_type,
			                tmpApplication,
			                _pointerID,
			                gale::key::statusUpAfter,
			                _pos);
			// specific for tuch event
			if (_type == gale::key::typeFinger) {
				cleanElement(eventTable, _pointerID);
			}
		}
	}
}
示例#24
0
static void
handle_readable(EventSelector *es,
		int fd,
		unsigned int flags,
		void *data)
{
    EventTcpState *state = (EventTcpState *) data;
    int done = state->cur - state->buf;
    int togo = state->len - done;
    int nread = 0;
    int flag;

    EVENT_DEBUG(("tcp_handle_readable(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data));

    
    if (flags & EVENT_FLAG_TIMEOUT) {
	errno = ETIMEDOUT;
	(state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_TIMEOUT,
		   state->data);
	free_state(state);
	return;
    }
    if (state->delim < 0) {
	
	
	nread = read(fd, state->cur, togo);
	if (nread <= 0) {
	    if (nread < 0 && errno == ECONNRESET && done > 0) {
		nread = 0;
	    }
	    flag = (nread) ? EVENT_TCP_FLAG_IOERROR : EVENT_TCP_FLAG_EOF;
	    
	    (state->f)(es, state->socket, state->buf, done, flag, state->data);
	    free_state(state);
	    return;
	}
	state->cur += nread;
	done += nread;
	if (done >= state->len) {
	    
	    (state->f)(es, state->socket, state->buf, done,
		       EVENT_TCP_FLAG_COMPLETE, state->data);
	    free_state(state);
	    return;
	}
    } else {
	
	while ( (togo > 0) && (nread = read(fd, state->cur, 1)) == 1) {
	    togo--;
	    done++;
	    state->cur++;
	    if (*(state->cur - 1) == state->delim) break;
	}

	if (nread <= 0) {
	    
	    if (nread < 0 && errno == EAGAIN) return;
	}

	
	if (nread < 0) {
	    flag = EVENT_TCP_FLAG_IOERROR;
	} else if (nread == 0) {
	    flag = EVENT_TCP_FLAG_EOF;
	} else {
	    flag = EVENT_TCP_FLAG_COMPLETE;
	}
	(state->f)(es, state->socket, state->buf, done, flag, state->data);
	free_state(state);
	return;
    }
}
示例#25
0
/**********************************************************************
* %FUNCTION: handle_readable
* %ARGUMENTS:
*  es -- event selector
*  fd -- the readable socket
*  flags -- ignored
*  data -- the EventTcpState object
* %RETURNS:
*  Nothing
* %DESCRIPTION:
*  Continues to fill buffer.  Calls callback when done.
***********************************************************************/
static void
handle_readable(EventSelector *es,
		int fd,
		unsigned int flags,
		void *data)
{
    EventTcpState *state = (EventTcpState *) data;
    int done = state->cur - state->buf;
    int togo = state->len - done;
    int nread = 0;
    int flag;

    EVENT_DEBUG(("tcp_handle_readable(es=%p, fd=%d, flags=%u, data=%p)\n", es, fd, flags, data));

    /* Timed out? */
    if (flags & EVENT_FLAG_TIMEOUT) {
	errno = ETIMEDOUT;
	(state->f)(es, state->socket, state->buf, done, EVENT_TCP_FLAG_TIMEOUT,
		   state->data);
	free_state(state);
	return;
    }
    if (state->delim < 0) {
	/* Not looking for a delimiter */
	/* togo had better not be zero here! */
	nread = read(fd, state->cur, togo);
	if (nread <= 0) {
	    /* Change connection reset to EOF if we have read at least
	       one char */
	    if (nread < 0 && errno == ECONNRESET && done > 0) {
		nread = 0;
	    }
	    flag = (nread) ? EVENT_TCP_FLAG_IOERROR : EVENT_TCP_FLAG_EOF;
	    /* error or EOF */
	    (state->f)(es, state->socket, state->buf, done, flag, state->data);
	    free_state(state);
	    return;
	}
	state->cur += nread;
	done += nread;
	if (done >= state->len) {
	    /* Read enough! */
	    (state->f)(es, state->socket, state->buf, done,
		       EVENT_TCP_FLAG_COMPLETE, state->data);
	    free_state(state);
	    return;
	}
    } else {
	/* Looking for a delimiter */
	while ( (togo > 0) && (nread = read(fd, state->cur, 1)) == 1) {
	    togo--;
	    done++;
	    state->cur++;
	    if (*(state->cur - 1) == state->delim) break;
	}

	if (nread <= 0) {
	    /* Error or EOF -- check for EAGAIN */
	    if (nread < 0 && errno == EAGAIN) return;
	}

	/* Some other error, or EOF, or delimiter, or read enough */
	if (nread < 0) {
	    flag = EVENT_TCP_FLAG_IOERROR;
	} else if (nread == 0) {
	    flag = EVENT_TCP_FLAG_EOF;
	} else {
	    flag = EVENT_TCP_FLAG_COMPLETE;
	}
	(state->f)(es, state->socket, state->buf, done, flag, state->data);
	free_state(state);
	return;
    }
}
示例#26
0
/**********************************************************************
* %FUNCTION: EventTcp_WriteBuf
* %ARGUMENTS:
*  es -- event selector
*  socket -- socket to read from
*  buf -- buffer to write
*  len -- number of bytes to write
*  f -- function to call on EOF or when all bytes have been read
*  timeout -- timeout after which to cancel operation
*  data -- extra data to pass to function f.
* %RETURNS:
*  A new EventTcpState token or NULL on error
* %DESCRIPTION:
*  Sets up a handler to fill a buffer from a socket.
***********************************************************************/
EventTcpState *
EventTcp_WriteBuf(EventSelector *es,
		  int socket,
		  char *buf,
		  int len,
		  EventTcpIOFinishedFunc f,
		  int timeout,
		  void *data)
{
    EventTcpState *state;
    int flags;
    struct timeval t;

    EVENT_DEBUG(("EventTcp_WriteBuf(es=%p, socket=%d, len=%d, timeout=%d)\n", es, socket, len, timeout));
    if (len <= 0) return NULL;
    if (socket < 0) return NULL;

    /* Make sure socket is non-blocking */
    flags = fcntl(socket, F_GETFL, 0);
    if (flags == -1) {
	return NULL;
    }
    if (fcntl(socket, F_SETFL, flags | O_NONBLOCK) == -1) {
	return NULL;
    }

    state = malloc(sizeof(EventTcpState));
    if (!state) return NULL;

    memset(state, 0, sizeof(EventTcpState));

    state->socket = socket;

    state->buf = malloc(len);
    if (!state->buf) {
	free_state(state);
	return NULL;
    }
    memcpy(state->buf, buf, len);

    state->cur = state->buf;
    state->len = len;
    state->f = f;
    state->es = es;

    if (timeout <= 0) {
	t.tv_sec = -1;
	t.tv_usec = -1;
    } else {
	t.tv_sec = timeout;
	t.tv_usec = 0;
    }

    state->eh = Event_AddHandlerWithTimeout(es, socket, EVENT_FLAG_WRITEABLE,
					    t, handle_writeable,
					    (void *) state);
    if (!state->eh) {
	free_state(state);
	return NULL;
    }

    state->data = data;
    state->delim = -1;
    EVENT_DEBUG(("EventTcp_WriteBuf() -> %p\n", state));
    return state;
}
示例#27
0
void ewol::context::InputManager::state(enum gale::key::type _type,
                                        int _pointerID,
                                        bool _isDown,
                                        vec2 _pos) {
	if (_pointerID >= MAX_MANAGE_INPUT) {
		// reject pointer  == > out of IDs...
		return;
	}
	EVENT_DEBUG("event pointerId=" << _pointerID);
	// convert position in open-GL coordonates ...
	InputPoperty *eventTable = nullptr;
	InputLimit   localLimit;
	if (_type == gale::key::type::mouse) {
		eventTable = m_eventMouseSaved;
		localLimit = m_eventMouseLimit;
	} else if (_type == gale::key::type::finger) {
		eventTable = m_eventInputSaved;
		localLimit = m_eventInputLimit;
	} else {
		EWOL_ERROR("Unknown type of event");
		return;
	}
	if(    _pointerID > MAX_MANAGE_INPUT
	    || _pointerID <= 0) {
		// not manage input
		return;
	}
	// get the curent time ...
	echrono::Clock currentTime = echrono::Clock::now();
	ewol::widget::WindowsShared tmpWindows = m_context.getWindows();
	
	if (_isDown == true) {
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		             << " == >" << eventTable[_pointerID].destinationInputId
		             << " [DOWN] " << _pos);
		if(eventTable[_pointerID].isUsed == true) {
			// we have an event previously ... check delay between click and offset position
			if (currentTime - eventTable[_pointerID].lastTimeEvent > localLimit.sepatateTime) {
				cleanElement(eventTable, _pointerID);
			} else if(    std::abs(eventTable[_pointerID].downStart.x() - _pos.x()) >= localLimit.DpiOffset
			           || std::abs(eventTable[_pointerID].downStart.y() - _pos.y()) >= localLimit.DpiOffset ){
				cleanElement(eventTable, _pointerID);
			}
		}
		if(eventTable[_pointerID].isUsed == true) {
			// save start time
			eventTable[_pointerID].lastTimeEvent = currentTime;
			// generate DOWN Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [DOWN]   " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                eventTable[_pointerID].curentWidgetEvent.lock(),
			                eventTable[_pointerID].destinationInputId,
			                gale::key::status::down,
			                _pos);
		} else {
			// Mark it used :
			eventTable[_pointerID].isUsed = true;
			// Save current position :
			eventTable[_pointerID].downStart = _pos;
			// save start time
			eventTable[_pointerID].lastTimeEvent = currentTime;
			// set the element inside ...
			eventTable[_pointerID].isInside = true;
			ewol::WidgetShared tmpWidget = m_grabWidget.lock();
			// get destination widget :
			if(tmpWindows != nullptr) {
				if (    tmpWidget != nullptr
				     && _type == gale::key::type::mouse) {
					eventTable[_pointerID].curentWidgetEvent = tmpWidget;
				} else {
					tmpWidget = tmpWindows->getWidgetAtPos(_pos);
					eventTable[_pointerID].curentWidgetEvent = tmpWidget;
					if (tmpWidget != nullptr) {
						EVENT_DEBUG("Get widget at pos=" << _pos << " type: " << tmpWidget->getObjectType());
					} else {
						EVENT_DEBUG("Get widget at pos=" << _pos << " NO WIDGET");
					}
				}
			} else {
				eventTable[_pointerID].curentWidgetEvent.reset();
			}
			tmpWidget = eventTable[_pointerID].curentWidgetEvent.lock();
			if (tmpWidget != nullptr) {
				eventTable[_pointerID].origin = tmpWidget->getOrigin();
				eventTable[_pointerID].size = tmpWidget->getSize();
				eventTable[_pointerID].destinationInputId = localGetDestinationId(_type, tmpWidget, _pointerID);
			} else {
				eventTable[_pointerID].destinationInputId = -1;
			}
			// generate DOWN Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [DOWN]   " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			localEventInput(_type,
			                tmpWidget,
			                eventTable[_pointerID].destinationInputId,
			                gale::key::status::down,
			                _pos);
		}
	} else {
		EVENT_DEBUG("GUI : Input ID=" << _pointerID
		             << " == >" << eventTable[_pointerID].destinationInputId
		             << " [UP]     " << _pos);
		ewol::WidgetShared tmpWidget = eventTable[_pointerID].curentWidgetEvent.lock();
		if(eventTable[_pointerID].isUsed == false) {
			// bad case ... ???
			EWOL_DEBUG("Up event without previous down ... ");
			// Mark it un-used :
			eventTable[_pointerID].isUsed = false;
			// revove the widget ...
			eventTable[_pointerID].curentWidgetEvent.reset();
		} else if (tmpWidget == nullptr) {
			// The widget has been removed:
			EVENT_DEBUG("    Object Removed ...");
			// Mark it un-used :
			eventTable[_pointerID].isUsed = false;
			// revove the widget ...
			eventTable[_pointerID].curentWidgetEvent.reset();
		} else {
			// generate UP Event
			EVENT_DEBUG("GUI : Input ID=" << _pointerID
			            << " == >" << eventTable[_pointerID].destinationInputId
			            << " [UP]     " << _pos);
			eventTable[_pointerID].posEvent = _pos;
			// send up event after the single event to prevent multiple widget getting elements
			localEventInput(_type,
			                tmpWidget,
			                _pointerID,
			                gale::key::status::up,
			                _pos);
			// generate event (single)
			if(    std::abs(eventTable[_pointerID].downStart.x() - _pos.x()) < localLimit.DpiOffset
			    && std::abs(eventTable[_pointerID].downStart.y() - _pos.y()) < localLimit.DpiOffset ){
				// Save current position :
				eventTable[_pointerID].downStart = _pos;
				// save start time
				eventTable[_pointerID].lastTimeEvent = currentTime;
				int32_t nbClickMax = 0;
				if(tmpWidget != nullptr) {
					nbClickMax = tmpWidget->getMouseLimit();
					if (nbClickMax>5) {
						nbClickMax = 5;
					}
				}
				// in grab mode the single to quinte event are not generated ....
				if(    (    m_grabWidget.lock() == nullptr
				         || _type != gale::key::type::mouse )
				    && eventTable[_pointerID].nbClickEvent < nbClickMax) {
					// generate event SINGLE :
					eventTable[_pointerID].nbClickEvent++;
					EVENT_DEBUG("GUI : Input ID=" << _pointerID
					            << " == >" << eventTable[_pointerID].destinationInputId
					            << " [" << eventTable[_pointerID].nbClickEvent << "] " << _pos);
					eventTable[_pointerID].posEvent = _pos;
					localEventInput(_type,
					                tmpWidget,
					                eventTable[_pointerID].destinationInputId,
					                (enum gale::key::status)(uint32_t(gale::key::status::pressSingle) + eventTable[_pointerID].nbClickEvent-1),
					                _pos);
					if( eventTable[_pointerID].nbClickEvent >= nbClickMax) {
						eventTable[_pointerID].nbClickEvent = 0;
					}
				} else {
					eventTable[_pointerID].nbClickEvent = 0;
				}
			}
			// send up event after the single event to prevent multiple widget getting elements
			localEventInput(_type,
			                tmpWidget,
			                _pointerID,
			                gale::key::status::upAfter,
			                _pos);
			// specific for tuch event
			if (_type == gale::key::type::finger) {
				cleanElement(eventTable, _pointerID);
			}
		}
	}
}