#include "select_helper.h"


int select_helper(select_helper_data *seldata, struct timeval *timeout) {

    seldata->readfds_ready = seldata->readfds;
    seldata->writefds_ready = seldata->writefds;

    #ifdef _WIN32

        seldata->exceptfds_ready = seldata->exceptfds;

        int result = select(
            0,  // ignored by the Windows implementation
            &seldata->readfds_ready,
            &seldata->writefds_ready,
            &seldata->exceptfds_ready,
            timeout
        );

        if (result < 0) {
            int error = WSAGetLastError();
            if (error == WSAEINVAL) {
                // This means all fd_sets were empty. Not an error.
                result = 0;
                // select() returned instantly, unlike on other platforms.
                // Force a sleep here to retain expected behavior.
                if (timeout) {
                    DWORD s = timeout->tv_sec;
                    DWORD us = timeout->tv_usec;
                    DWORD ms = (s * 1000) + (us / 1000);
                    Sleep(ms);
                }
            }
        }

    #else

        int result = select(
            seldata->nfds,
            &seldata->readfds_ready,
            &seldata->writefds_ready,
            NULL,
            timeout
        );

    #endif

    clock_gettime(CLOCK_REALTIME, &seldata->tp);
    seldata->timestamp = timestamp_from_timespec(&seldata->tp);

    return result;

}
