コード例 #1
0
ファイル: input_common.cpp プロジェクト: kballard/fish-shell
/// Internal function used by input_common_readch to read one byte from fd 0. This function should
/// only be called by input_common_readch().
static char_event_t readb() {
    // do_loop must be set on every path through the loop; leaving it uninitialized allows the
    // static analyzer to assist in catching mistakes.
    unsigned char arr[1];
    bool do_loop;

    do {
        // Flush callbacks.
        input_flush_callbacks();

        fd_set fdset;
        int fd_max = 0;
        int ioport = iothread_port();
        int res;

        FD_ZERO(&fdset);
        FD_SET(0, &fdset);
        if (ioport > 0) {
            FD_SET(ioport, &fdset);
            fd_max = std::max(fd_max, ioport);
        }

        // Get our uvar notifier.
        universal_notifier_t &notifier = universal_notifier_t::default_notifier();

        // Get the notification fd (possibly none).
        int notifier_fd = notifier.notification_fd();
        if (notifier_fd > 0) {
            FD_SET(notifier_fd, &fdset);
            fd_max = std::max(fd_max, notifier_fd);
        }

        // Get its suggested delay (possibly none).
        struct timeval tv = {};
        const unsigned long usecs_delay = notifier.usec_delay_between_polls();
        if (usecs_delay > 0) {
            unsigned long usecs_per_sec = 1000000;
            tv.tv_sec = (int)(usecs_delay / usecs_per_sec);
            tv.tv_usec = (int)(usecs_delay % usecs_per_sec);
        }

        res = select(fd_max + 1, &fdset, 0, 0, usecs_delay > 0 ? &tv : NULL);
        if (res == -1) {
            if (errno == EINTR || errno == EAGAIN) {
                if (interrupt_handler) {
                    if (auto interrupt_evt = interrupt_handler()) {
                        return *interrupt_evt;
                    } else if (auto mc = lookahead_pop_evt()) {
                        return *mc;
                    }
                }

                do_loop = true;
            } else {
                // The terminal has been closed.
                return char_event_type_t::eof;
            }
        } else {
            // Assume we loop unless we see a character in stdin.
            do_loop = true;

            // Check to see if we want a universal variable barrier.
            bool barrier_from_poll = notifier.poll();
            bool barrier_from_readability = false;
            if (notifier_fd > 0 && FD_ISSET(notifier_fd, &fdset)) {
                barrier_from_readability = notifier.notification_fd_became_readable(notifier_fd);
            }
            if (barrier_from_poll || barrier_from_readability) {
                env_universal_barrier();
            }

            if (ioport > 0 && FD_ISSET(ioport, &fdset)) {
                iothread_service_completion();
                if (auto mc = lookahead_pop_evt()) {
                    return *mc;
                }
            }

            if (FD_ISSET(STDIN_FILENO, &fdset)) {
                if (read_blocked(0, arr, 1) != 1) {
                    // The teminal has been closed.
                    return char_event_type_t::eof;
                }

                // We read from stdin, so don't loop.
                do_loop = false;
            }
        }
    } while (do_loop);

    return arr[0];
}
コード例 #2
0
ファイル: input_common.cpp プロジェクト: ALSchwalm/fish-shell
/**
   Internal function used by input_common_readch to read one byte from fd 0. This function should only be called by
   input_common_readch().
*/
static wint_t readb()
{
    /* do_loop must be set on every path through the loop; leaving it uninitialized allows the static analyzer to assist in catching mistakes. */
    unsigned char arr[1];
    bool do_loop;

    do
    {
        /* Flush callbacks */
        input_flush_callbacks();

        fd_set fdset;
        int fd_max = 0;
        int ioport = iothread_port();
        int res;

        FD_ZERO(&fdset);
        FD_SET(0, &fdset);
        if (ioport > 0)
        {
            FD_SET(ioport, &fdset);
            fd_max = maxi(fd_max, ioport);
        }
        
        /* Get our uvar notifier */
        universal_notifier_t &notifier = universal_notifier_t::default_notifier();
        
        /* Get the notification fd (possibly none) */
        int notifier_fd = notifier.notification_fd();
        if (notifier_fd > 0)
        {
            FD_SET(notifier_fd, &fdset);
            fd_max = maxi(fd_max, notifier_fd);
        }
        
        /* Get its suggested delay (possibly none) */
        struct timeval tv = {};
        const unsigned long usecs_delay = notifier.usec_delay_between_polls();
        if (usecs_delay > 0)
        {
            unsigned long usecs_per_sec = 1000000;
            tv.tv_sec = (int)(usecs_delay / usecs_per_sec);
            tv.tv_usec = (int)(usecs_delay % usecs_per_sec);
        }
        
        res = select(fd_max + 1, &fdset, 0, 0, usecs_delay > 0 ? &tv : NULL);
        if (res==-1)
        {
            switch (errno)
            {
                case EINTR:
                case EAGAIN:
                {
                    if (interrupt_handler)
                    {
                        int res = interrupt_handler();
                        if (res)
                        {
                            return res;
                        }
                        if (has_lookahead())
                        {
                            return lookahead_pop();
                        }

                    }


                    do_loop = true;
                    break;
                }
                default:
                {
                    /*
                      The terminal has been closed. Save and exit.
                    */
                    return R_EOF;
                }
            }
        }
        else
        {
            /* Assume we loop unless we see a character in stdin */
            do_loop = true;

            /* Check to see if we want a universal variable barrier */
            bool barrier_from_poll = notifier.poll();
            bool barrier_from_readability = false;
            if (notifier_fd > 0 && FD_ISSET(notifier_fd, &fdset))
            {
                barrier_from_readability = notifier.notification_fd_became_readable(notifier_fd);
            }
            if (barrier_from_poll || barrier_from_readability)
            {
                env_universal_barrier();
            }

            if (ioport > 0 && FD_ISSET(ioport, &fdset))
            {
                iothread_service_completion();
                if (has_lookahead())
                {
                    return lookahead_pop();
                }
            }

            if (FD_ISSET(STDIN_FILENO, &fdset))
            {
                if (read_blocked(0, arr, 1) != 1)
                {
                    /* The teminal has been closed. Save and exit. */
                    return R_EOF;
                }

                /* We read from stdin, so don't loop */
                do_loop = false;
            }
        }
    }
    while (do_loop);

    return arr[0];
}