Welcome
Example Code
C and C++
Argument Parsing
Create Subprocess
Create Thread
Is Subprocess Done
Non-Blocking File (Unix)
Mutex (Lock)
TCP Server
Wait For File (Unix)
Python
Non-Blocking Read

Monju System Architects



Code - C++ - Wait For File (Unix)
Download: waitForDescriptor.cpp (the linked-to file is properly tabbed)
Requires: file.h, mutex.h, mutex.cpp, signal.h, signal.cpp, waitForDescriptor.h
//  Copyright (c) 2007, Monju System Architects
//
//  Released under the Monju-Public copyright license:
//
//  Permission is hereby granted, free of charge, to any person or entity
//  obtaining a copy of this software and associated documentation files
//  (the "Software"), to deal in the Software without restriction,
//  including without limitation the rights to use, copy, modify, merge,
//  publish, distribute, sublicense, and/or sell copies and modifications
//  of the Software, and to permit persons to whom the Software is
//  furnished to do so, subject to the following conditions:
//
//  The above copyright notice and this permission notice shall be
//  included in all copies or substantial portions of published, sold, or
//  ownership-transferred versions of the Software. The notices are not
//  required for binary-only releases or binary-only derivatives of the
//  Software, or documentation provided with binary-only releases and
//  binary-only derivatives.
//
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
//  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
//  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
//  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
//  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
//  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
//  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.



//  NOTE:  Unix only.
#ifndef _WIN32



//  INCLUDES.
#include <stdlib.h>
#include <sys/select.h>

#include "public/signal.h"
#include "public/waitForDescriptor.h"



//  EXTERNAL VARIABLES.
extern SIGNAL_TYPE g_shouldExitSignal;




//  waitUntilReadable()
//
//  Given a file descriptor, will wait the given amount of time (or forever if the time is 
//  less than zero) for the file descriptor to be readable.  Returns false if the
//  wait times out or if the system is exiting.
bool waitUntilReadable(int fileDescriptor) {
    return waitUntilReadable(fileDescriptor, NULL, -1, 0);
}
bool waitUntilReadable(int fileDescriptor, double timeout, bool* pTimedOut) {
    return waitUntilReadable(fileDescriptor, (int) timeout, (int) (timeout * 1000000.0), pTimedOut);
}
bool waitUntilReadable(int fileDescriptor, int timeoutSeconds, bool* pTimedOut) {
    return waitUntilReadable(fileDescriptor, timeoutSeconds, 0, pTimedOut);
}
bool waitUntilReadable(int fileDescriptor, int timeoutSeconds, int timeoutMicroseconds, bool* pTimedOut) {
    fd_set readFileDescriptors;

    //  ADD THE GIVEN AND THE SHOULD-EXIT DESCRIPTORS TO OUR LIST.
    FD_ZERO(&readFileDescriptors);
    FD_SET(fileDescriptor, &readFileDescriptors);
    FD_SET(g_shouldExitSignal.m_pipe[0], &readFileDescriptors);
    
    //  WAIT FOR EITHER DESCRIPTOR, HANDLE TIMEOUT AS APPROPRIATE.
    if (timeoutSeconds < 0) {
        select(2, &readFileDescriptors, NULL, NULL, NULL);
    }
    else {
        struct timeval      timeValue;
        int count           = 0;
        timeValue.tv_sec    = timeoutSeconds;
        timeValue.tv_usec   = timeoutMicroseconds;
        count = select(2, &readFileDescriptors, NULL, NULL, &timeValue);
        if (count == 0) {
            if (pTimedOut != NULL) {
                *pTimedOut = true;
            }
            return false;
        }
    }
    
    //  IF THE PASSED IN DESCRIPTOR IS READABLE, RETURN 'true'.
    if (FD_ISSET(fileDescriptor, &readFileDescriptors)) {
        return true;
    }
    return false;
}



//  waitUntilWriteable()
//
//  Given a file descriptor, will wait the given amount of time (or forever if the time is 
//  less than zero) for the file descriptor to be writeable.  Returns false if the
//  wait times out or if the system is exiting.
bool waitUntilWriteable(int fileDescriptor) {
    return waitUntilWriteable(fileDescriptor, NULL, -1, 0);
}
bool waitUntilWriteable(int fileDescriptor, double timeout, bool* pTimedOut) {
    return waitUntilWriteable(fileDescriptor, (int) timeout, (int) (timeout * 1000000.0), pTimedOut);
}
bool waitUntilWriteable(int fileDescriptor, int timeoutSeconds, bool* pTimedOut) {
    return waitUntilWriteable(fileDescriptor, timeoutSeconds, 0, pTimedOut);
}
bool waitUntilWriteable(int fileDescriptor, int timeoutSeconds, int timeoutMicroseconds, bool* pTimedOut) {
    fd_set readFileDescriptors;
    fd_set writeFileDescriptors;

    //  ADD THE GIVEN FILE DESCRIPTOR TO THE WRITE LIST.
    FD_ZERO(&writeFileDescriptors);
    FD_SET(fileDescriptor, &writeFileDescriptors);
    
    //  ADD THE SHOULD-EXIT DESCRIPTORS TO THE READ LIST.
    FD_ZERO(&readFileDescriptors);
    FD_SET(g_shouldExitSignal.m_pipe[0], &readFileDescriptors);

    //  WAIT FOR EITHER DESCRIPTOR, HANDLE TIMEOUT AS APPROPRIATE.
    if (timeoutSeconds < 0) {
        select(2, &readFileDescriptors, &writeFileDescriptors, NULL, NULL);
    }
    else {
        struct timeval      timeValue;
        int count           = 0;
        timeValue.tv_sec    = timeoutSeconds;
        timeValue.tv_usec   = timeoutMicroseconds;
        count = select(2, &readFileDescriptors, &writeFileDescriptors, NULL, &timeValue);
        if (count == 0) {
            if (pTimedOut != NULL) {
                *pTimedOut = true;
            }
            return false;
        }
    }
    
    //  IF THE PASSED IN DESCRIPTOR IS WRITABLE, RETURN 'true'.
    if (FD_ISSET(fileDescriptor, &writeFileDescriptors)) {
        return true;
    }
    return false;
}




#endif // #ifndef _WIN32