Ejemplo n.º 1
0
        void io_looper::loop_worker()
        {
            DWORD io_size;
            uintptr_t completion_key;
            LPOVERLAPPED lolp;
            DWORD error;

            while (true)
            {
                BOOL r = ::GetQueuedCompletionStatus(_io_queue, &io_size, &completion_key, &lolp, 1); // 1ms timeout for timers

                // everything goes fine
                if (r)
                {
                    error = ERROR_SUCCESS;
                }

                // failed or timeout
                else
                {
                    error = ::GetLastError();
                    if (error == ERROR_ABANDONED_WAIT_0)
                    {
                        derror("completion port loop exits");
                        break;
                    }

                    // only possible for timeout
                    if (NULL == lolp)
                    {
                        handle_local_queues();
                        continue;
                    }

                    dinfo("io operation failed in iocp, err = 0x%x", error);
                }

                if (NON_IO_TASK_NOTIFICATION_KEY == completion_key)
                {
                    handle_local_queues();
                }
                else
                {
                    io_loop_callback* cb = (io_loop_callback*)completion_key;
                    (*cb)((int)error, io_size, (uintptr_t)lolp);
                }
            }
        }
Ejemplo n.º 2
0
        void io_looper::loop_worker()
        {
            struct timespec ts = { 0, 1000000 };

            while (true)
            {
                int nfds = kevent(_io_queue, nullptr, 0, _events, IO_LOOPER_MAX_EVENT_COUNT, &ts); // 1ms for timers
                if (nfds == 0) // timeout
                {
                    handle_local_queues();
                    continue;
                }
                else if (-1 == nfds)
                {
                    if (errno == EINTR)
                    {
                        continue;
                    }                        
                    else
                    {
                        derror("epoll_wait loop exits, err = %s", strerror(errno));
                        break;
                    }
                }

                for (int i = 0; i < nfds; i++)
                {
                    auto cb = (io_loop_callback*)_events[i].udata;
                    dinfo("kevent get events %x, cb = %p", _events[i].filter, cb);

                    uintptr_t cb0 = (uintptr_t)cb;

                    // for those with ref_counter register entries
                    if (cb0 & 0x1)
                    {
                        cb = (io_loop_callback*)(cb0 - 1);

                        ref_counter* robj;
                        {

                            utils::auto_lock<utils::ex_lock_nr_spin> l(_io_sessions_lock);
                            auto it = _io_sessions.find(cb);
                            if (it != _io_sessions.end())
                            {
                                robj = it->second;
                                // make sure callback is protected by ref counting
                                robj->add_ref();
                            }
                            else
                            {
                                robj = nullptr;
                            }
                        }

                        if (robj)
                        {
                            (*cb)(0, 0, (uintptr_t)&_events[i]);
                            robj->release_ref();
                        }
                        else
                        {
                            // context is gone (unregistered), let's skip
                            dwarn("kevent event %x skipped as session is gone, cb = %p",
                                _events[i].filter,
                                cb
                                );
                        }
                    }
                    else
                    {
                        (*cb)(0, 0, (uintptr_t)&_events[i]);
                    }
                }
            }
        }