Thread: Processing both I/O and timed events

  1. #1
    Registered User
    Join Date
    Feb 2009
    Posts
    20

    Processing both I/O and timed events

    I have some aspirations of one day programming a MUD engine, and I will need to be able to handle both user I/O and timed events. I have written a little program that uses SIGALRM to update the time. I am wondering if I have a sensible "architecture" for the program, given that global variables should generally be avoided. The program is:

    Code:
    #include <stdlib.h>
    #include <stdio.h>
    #include <signal.h>
    #include <unistd.h>
    
    volatile unsigned int alarmTrig;
    
    static void alrmHandler(int x)  //indicates alarm triggered and resets same
    {
            alarmTrig = 1;
            alarm(1);
            return;
    }
    
    int main(int argc, char *argv[])
    {
            struct sigaction theHandler;    //sigaction struct
            char inpChar;
            int i, bytesRead = 0;
            sigset_t emptyMask;
    
            sigemptyset(&emptyMask);
            theHandler.sa_handler = alrmHandler;
            theHandler.sa_mask = emptyMask; //nothing special
            theHandler.sa_flags = 0;        //nothing special here
            theHandler.sa_restorer = NULL;  //option obsolete
    
            sigaction(SIGALRM, &theHandler, NULL);
            alarmTrig=0;
    
            alarm(1);
            for(i=0; i<20; i++)
            {
                    while(alarmTrig == 0)
                    {
                            bytesRead = fread(&inpChar, 1, 1, stdin);
                            if(bytesRead == 1)
                            {
                                    printf("You entered %c.\n",inpChar);
                            }
                    }
                    if (alarmTrig == 1)
                    {
                            alarmTrig=0;
                            printf("%d seconds have gone by.\n",i);
                            alarm(1);
                    }
            }
    
            return 0;
    }
    Ignoring for now that I do not continually flush the input buffer, is this a reasonable approach, with the alarm handler setting a global variable? Thank you.

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    >> ... given that global variables should generally be avoided.
    There are still times when they're needed.

    >> ... is this a reasonable approach, with the alarm handler setting a global variable?
    Yes - It's an ideal signal handler in general. However, global should be of type "volatile sig_atomic_t".

    gg

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    The select() system call with a timeout allows you to monitor i/o for activity, and allows you to observe the passage of time.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Feb 2009
    Posts
    20
    Quote Originally Posted by Codeplug View Post
    >>
    >> ... is this a reasonable approach, with the alarm handler setting a global variable?
    Yes - It's an ideal signal handler in general. However, global should be of type "volatile sig_atomic_t".

    gg

    Thanks. It's nice to know that my microcontroller work is applicable to a computer system.

    I was looking up sig_atomic_t, and it appears to be typedefed int, with its typedef being performed between
    Code:
    __BEGIN_NAMESPACE_STD
    
    and 
    
    __END_NAMESPACE_STD
    in <signal.h>. This ensures that changes are atomic. I have tried to find these in gcc's info file, but have not found them. What section would these be under? Thank you again.

  5. #5
    Registered User
    Join Date
    Feb 2009
    Posts
    20
    Quote Originally Posted by Salem View Post
    The select() system call with a timeout allows you to monitor i/o for activity, and allows you to observe the passage of time.
    Thanks. I knew Python had something similar for serial ports, but I had forgotten about select's timeout.

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by drunken_scot View Post
    Thanks. It's nice to know that my microcontroller work is applicable to a computer system.

    I was looking up sig_atomic_t, and it appears to be typedefed int, with its typedef being performed between
    Code:
    __BEGIN_NAMESPACE_STD
    
    and 
    
    __END_NAMESPACE_STD
    in <signal.h>. This ensures that changes are atomic. I have tried to find these in gcc's info file, but have not found them. What section would these be under? Thank you again.
    If you are asking what __BEGIN/__END_NAMESPAC_STD does, then that's for when you use <csignal> in C++, which included <signal.h>.

    The point is that sig_atomic_t is GUARANTEED to be of a type that can be accessed as a single operation, which is not guaranteed [but still possible] about other types such as int or long. [It happens that the C runtime for this environment KNOWS that int is OK for this purpose, but it's not necessarily the case for another environment].

    The select() solution is definitely one worth looking at.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User
    Join Date
    Feb 2009
    Posts
    20
    Quote Originally Posted by matsp View Post
    If you are asking what __BEGIN/__END_NAMESPAC_STD does, then that's for when you use <csignal> in C++, which included <signal.h>.
    That makes sense. Thanks.

Popular pages Recent additions subscribe to a feed

Tags for this Thread