Link to home
Start Free TrialLog in
Avatar of the_bikeman
the_bikeman

asked on

Independently running functions...

Hi all!  I am wondering how I can write a function (or some other method) that will run independantly of the rest of my program.  For example, a clock that will constantly update itself, or a count-down timer that counts down while the user is doing something else, like trying to answer a question.  I would appreciate some help here, especially some code examples.

the_bikeman
Avatar of feenix
feenix
Flag of Finland image

This can be accomplished with threads. What opertaing system are you using? If Windows, check out the cretethread function in your compiler's help file.
Avatar of bcoleman
bcoleman

Need operating system(Windows/linux)?
try multi thread
#include <windows.h>
_beginthread(funcpointer,0,&ID);
it will run the funcpointer on another thread ndependantly of the rest of your program

if i didn't understand your prob right explaine it to me
Avatar of the_bikeman

ASKER

I am running on the Windows OS, though my program is actually for DOS.  If someone has a solution for Windows but not DOS, I'll live with it, as the program probably will never be run in a DOS only environment anyway.

ntdragon:  could you give me an example of using
                  _beginthread()?

the_bikeman
ASKER CERTIFIED SOLUTION
Avatar of nisa
nisa

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
A warning about threads: be *very* careful how you use them. For instance, if you don't use the proper synchronisation functions when accessing global data from your second thread, you could end up with all sorts of niggling bugs which will be near impossible to find.
Thanks, Nisa!  I'll try that, and if it works, I'll accept that as an answer.  I love this place, it gets some tough problems solved fairly quickly!

the_bikeman
If you only want to perform very simple tasks like counting down in that DOS program you could link the routine into the timer interrupt. Your function will then be executed approx. 18 time per second.
ok i see you got an example allready but i"ll give another one


#pragma hdrstop
#include <condefs.h>


//---------------------------------------------------------------------------
#pragma argsused
/*  Bounce - Creates a new thread each time the letter 'a' is typed.
 *  Each thread bounces a happy face of a different color around the screen.
 *  All threads are terminated when the letter 'Q' is entered.
 *
 *  This program requires the multithread library. For example, compile
 *  with the following command line:
 *      CL /MT BOUNCE.C
 */

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>
#include <process.h>

#define MAX_THREADS  32

/* getrandom returns a random number between min and max, which must be in
 * integer range.
 */
#define getrandom( min, max ) ((rand() % (int)(((max) + 1) - (min))) + (min))

void main( void );                     /* Thread 1: main */
void KbdFunc( void  );                 /* Keyboard input, thread dispatch */
void BounceProc( void * MyID1 );        /* Threads 2 to n: display */
void ClearScreen( void );              /* Screen clear */
void ShutDown( void );                 /* Program shutdown */
void WriteTitle( int ThreadNum );      /* Display title bar information */

HANDLE  hConsoleOut;                   /* Handle to the console */
HANDLE  hRunMutex;                     /* "Keep Running" mutex */
HANDLE  hScreenMutex;                  /* "Screen update" mutex  */
int     ThreadNr;                      /* Number of threads started */
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;   /* Console information */


void main()                            /* Thread One */
{
    /* Get display screen information & clear the screen.*/
    hConsoleOut = GetStdHandle( STD_OUTPUT_HANDLE );
    GetConsoleScreenBufferInfo( hConsoleOut, &csbiInfo );
    ClearScreen();
    WriteTitle( 0 );
    /* Create the mutexes and reset thread count. */
    hScreenMutex = CreateMutex( NULL, FALSE, NULL );   /* Cleared */
    hRunMutex = CreateMutex( NULL, TRUE, NULL );       /* Set */
    ThreadNr = 0;

    /* Start waiting for keyboard input to dispatch threads or exit. */
    KbdFunc();

    /* All threads done. Clean up handles. */
    CloseHandle( hScreenMutex );
    CloseHandle( hRunMutex );
    CloseHandle( hConsoleOut );
}

void ShutDown( void )                  /* Shut down threads */
{
    while ( ThreadNr > 0 )
    {
            /* Tell thread to die and record its death. */
            ReleaseMutex( hRunMutex );
            ThreadNr--;  
    }
    /* Clean up display when done */
    WaitForSingleObject( hScreenMutex, INFINITE );
    ClearScreen();
}

void KbdFunc( void )                   /* Dispatch and count threads. */
{
    int         KeyInfo;

    do
    {
        KeyInfo = _getch();
        if( tolower( KeyInfo ) == 'a' && ThreadNr < MAX_THREADS )
        {
            ThreadNr++;
            _beginthread( BounceProc, 0, &ThreadNr );
            WriteTitle( ThreadNr );
        }
    } while( tolower( KeyInfo ) != 'q' );

    ShutDown();
}

void BounceProc( void *MyID1 )
{
    char *MyID=(char*)MyID1;
    char      MyCell, OldCell;
    WORD      MyAttrib, OldAttrib;
    char      BlankCell = 0x20;
    COORD     Coords, Delta;
    COORD     Old = {0,0};
    DWORD     Dummy;

/* Generate update increments and initial display coordinates. */
    srand( (unsigned) *MyID * 3 );
    Coords.X = getrandom( 0, csbiInfo.dwSize.X - 1 );
    Coords.Y = getrandom( 0, csbiInfo.dwSize.Y - 1 );
    Delta.X = getrandom( -3, 3 );
    Delta.Y = getrandom( -3, 3 );

    /* Set up "happy face" & generate color attribute from thread number.*/
    if( *MyID > 16)
        MyCell = 0x01;                 /* outline face */
    else
        MyCell = 0x02;                 /* solid face */
    MyAttrib =  *MyID & 0x0F;          /* force black background */

    do
    {
        /* Wait for display to be available, then lock it. */
        WaitForSingleObject( hScreenMutex, INFINITE );

        /* If we still occupy the old screen position, blank it out. */
        ReadConsoleOutputCharacter( hConsoleOut, &OldCell, 1, Old, &Dummy );
        ReadConsoleOutputAttribute( hConsoleOut, &OldAttrib, 1, Old, &Dummy );
        if (( OldCell == MyCell ) && (OldAttrib == MyAttrib))
            WriteConsoleOutputCharacter( hConsoleOut, &BlankCell, 1, Old, &Dummy );

        /* Draw new face, then clear screen lock */
        WriteConsoleOutputCharacter( hConsoleOut, &MyCell, 1, Coords, &Dummy );
        WriteConsoleOutputAttribute( hConsoleOut, &MyAttrib, 1, Coords, &Dummy );
        ReleaseMutex( hScreenMutex );

        /* Increment the coordinates for next placement of the block. */
        Old.X = Coords.X;
        Old.Y = Coords.Y;
        Coords.X += Delta.X;
        Coords.Y += Delta.Y;

        /* If we are about to go off the screen, reverse direction */
        if( Coords.X < 0 || Coords.X >= csbiInfo.dwSize.X )
        {
            Delta.X = -Delta.X;
            Beep( 400, 50 );
        }
        if( Coords.Y < 0 || Coords.Y > csbiInfo.dwSize.Y )
        {
            Delta.Y = -Delta.Y;
            Beep( 600, 50 );
        }
    }
    /* Repeat while RunMutex is still taken. */
    while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT );

}

void WriteTitle( int ThreadNum )
{
    char    NThreadMsg[80];

    sprintf( NThreadMsg, "Threads running: %02d.  Press 'A' to start a thread,'Q' to quit.", ThreadNum );
    SetConsoleTitle( NThreadMsg );
}

void ClearScreen( void )
{
    DWORD    dummy;
    COORD    Home = { 0, 0 };
    FillConsoleOutputCharacter( hConsoleOut, ' ', csbiInfo.dwSize.X * csbiInfo.dwSize.Y, Home, &dummy );
}


this is from msdn lib i compiled it in C++Builder

now a little bit about it
the _beginthread func will get a pointer to function and it runs it on another thread
the idea is that using it you can run a func indepandly to the rest of your prog
the func and your prog will run at the same time
Adjusted points from 100 to 200
When I posted the question I did not expect to receive such great feedback and answers.  Huge thanks to Nisa and NtDragon!!!

the_bikeman
Nisa:

I compiled your program exactly as you gave it to me, but I get a compiler error:  undefined reference to '_beginthread'

Could you help me out here?
Another note, I am using Gcc for DOS, and I don't have the windows.h library that NtDragon refered to.

the_bikeman
Threads are only available when writing a Windows application (or a Windows console-mode application). If you're actually writing a 16-bit DOS application, you won't be able to use them.
Djgpp is a 32-bit development tool, not 16-bit.  And I am running under windows, so it really isn't a 16-bit application, is it?

the_bikeman
Of course it is, if it's written as one. All those old 16-bit DOS programs which run fine on Win9x don't miraculously become 32-bit just because they're running under Windows. Bottom line: if the EXE file produced by your compiler will run in DOS mode (i.e. when Windows isn't running), it isn't a Win32 console application and won't be able to use threads.
Hi,
  You have to include:
#include <windows.h>
#include <winbase.h>

Also this program need to use a multithreaded library. If VC++ then u have to compile with /MT compiler switch. I never have experience with gcc compiler. Is there any documentation of the compiler that discuss about compiling with multithreaded library?. A decent "modern" C/C++ compiler should have support a multithreaded library.


Best Regards,


Nisa.

 
first the windows.h header you can get from the net if you don't have it

second i got this error when i tried to compile it in vc so i tried C++Builder and it worked fine there

so if you can compile it in your gcc compiler try another one
<if you can try C++Builder i mean borland compiler>
the_bikeman> Djgpp is a 32-bit development tool, not 16-bit.
the_bikeman> And I am running under windows, so it really isn't a
the_bikeman> 16-bit application, is it?

pjknibbs> Of course it is, if it's written as one.
pjknibbs> All those old 16-bit DOS programs which run fine on Win9x
pjknibbs> don't miraculously become 32-bit just because they're
pjknibbs> running under Windows.

If you are using djgpp the programs _are_ 32-bit, however they can not access the Win32 API -- and thus can not use Windows threads. There seems however to be an implementation of the POSIX thread library for djgpp available at:

  ftp://ftp.cs.fsu.edu/pub/PART/PTHREADS/pthreads.zip

regards