You are here:

C++/timed macros

Advertisement


Question
I'm doing a program for my engineering class where I need to ask a series of questions every 5 minutes that takes in sets of information and my teacher has no idea how to do it so I was wonder if it's possible.

Answer
Firstly I would like to say that your use of the term "macros" has me a little confused and worried that possibly you are not in fact using C++.

As you are asking this of myself as a C++ expert in the C++ question category I shall presume this is the programming language you are using.

Another point is that you do not state what platform you are using - e.g. 32-bit MS Windows or Linux / UNIX or even (as you mention its for engineering) an embedded system.

When using C++ on mainstream desktop and server systems using UNIX/Linux/Mac OS X/MS Windows etc, or other operating system, then it has the full C++ standard library available. This is known as a hosted implementation.

When using C++ for really low level embedded or systems work, where no operating system is available, then no such set of library facilities are available. This is known as a freestanding implementation.

However in neither case can we implement what you are after in an efficient manner using just the features of ISO/ANSI standard C++ - with or without a full C++ standard library.

With a hosted implementation with access to the features of the C++ standard library we can do a sort of OK job.

Basically what your problem boils down to is (in pseudo code):

   Repeat (Until Bored ?)
       AskQuestions
       WaitForFiveMinutes
   End Repeat

It is the wait for 5 minutes that is the problem. The only way to do this using standard C++ library facilities is very busily using something similar to:

   Procedure WaitForFiveMinutes:
       Get TimeNow
       Set StartTime = TimeNow
       While Difference Between TimeNow And StarTime < 5 minutes
         Get TimeNow
       End While
   End Procedure

The loop:

   While Difference Between TimeNow And StarTime < 5 minutes
       Get TimeNow
   End While

will keep your program's process, and thereby the whole processor or processor core it is running on, very busy.

[Note:

We can use the time function to obtain the current calendar time represented as some value from some past point in time (the epoch) as time_t values and use the difftime function to obtain the difference in seconds between two such times as a double.

Alternatively we can get the time in clock ticks as a clock_t value using the clock function. This represents an approximation of the processor time used by a program. Subtracting one such value from another gets us the elapsed (processor usage) time between the calls to clock. We can use the CLOCKS_PER_SEC pre-processor macro value to convert clock tick (difference) values to seconds. This would be less accurate on a system running multiple processes per processor as your program process would not be the only process using processor time.

These functions and types are all inherited from the C standard library - include <ctime. (or <time.h> for C) to use them.

-- end note]

On a multitasking system in particular it is very wasteful of system resources. It ties up one processor or processor core continuously while running and will max out that processor (core) at or near 100% usage for the duration. Obviously, on a preemptive multitasking system if the process or thread in question is running at normal or low priority it should not prevent it from being pre-empted by higher priority processes or threads so the system should not fail, but it may become less responsive if it only has a single processor (core) to share all the work around.

Luckily, such operating systems usually come with facilities available to application programs (i.e. APIs - application program interfaces) to handle such situations in a more efficient fashion. The simplest such facility is to put a process or thread to sleep for a specified amount of time. This is much more efficient as the operating system will not schedule a sleeping process or thread for execution for the requested duration of the sleep. If other processes or threads have work to do in this time then they will be able to run without having to share processor cycles with a process or thread that is just hanging around waiting. When the sleep time is up the operating system will schedule the previously sleeping process or thread for execution once again. Note that this does not mean it will necessarily execute immediately when the sleep time is up but will be considered for execution along with all other processes or threads when next the operating system next looks for something (else) to execute. However as you are using wait time specified in minutes, the system's idea of not immediately will probably not be an issue.

[Note:

I am saying 'process or thread' above because some operating systems schedule processes and others threads (of which a process has one or more).

-- end note].

The down side of operating system APIs is that they are operating system specific.

POSIX (UNIX like) operating systems (UNIX / Linux / Mac OS X etc.) will have the functions sleep and nanosleep. The sleep function takes a time to sleep in seconds whereas nanosleep takes a structure indicating the time to sleep in nanoseconds. In this case I would think the sleep function would offer acceptable resolution - as 5 minutes is 300 seconds.

Microsoft Windows Win32/Win64 APIs have a Sleep function (note the uppercase 'S'). This takes a value of time to sleep in milliseconds (so 5 minutes equals 300,000 millisecond).

Here is a very simple example in C++.

   #include <iostream>     // For console output
   #include <ctime>        // for time_t, time and ctime

   // Define WaitForFiveMinutes to sleep for 5 minutes using available API function
   // If we compile with the pre-processor macro PLATFORM_IS_WIN32 defined then
   // we call the Win32 Sleep function with the value in milliseconds.
   // If we compile with the pre-processor macro PLATFORM_IS_POSIX defined then
   // we use the POSIX sleep function with the value in seconds.
   // If neither are defined we fail the compilation

   #if defined PLATFORM_IS_WIN32
   # include <windows.h>

   void WaitForFiveMinutes()
   {
     Sleep( 5*60*1000 ); // sleep for 5 minutes converted to milliseconds
   }

   #elif defined PLATFORM_IS_POSIX

   void WaitForFiveMinutes()
   {
     sleep( 5*60 ); // sleep for 5 minutes converted to seconds
   }

   #else

   # error Unsupported platform.

   #endif

   // Dummy implementation of a function to ask, receive and process questions.
   // Obtains the current time as a time_t value then displays it in a textual
   // form showing local time using ctime.
   // For full C++-ness these are considered to be in the C++ std namespace. As
   // they are inherited from the C library they are also in the global namespace.
   void AskQuestions()
   {
     std::time_t calendar_time( std::time(0) );
     std::cout << std::ctime( &calendar_time )
         << "Ask (and process) questions."
         << std::endl
         ;
   }

   // Main: loops forever calling AskQuestions and WaitForFiveMinutes.
   int main()
   {
       while ( true )      // Or for (;;)
       {
         AskQuestions();
         WaitForFiveMinutes();
       }
   }

Note that I have not specified any termination criteria for the ask - wait loop as none were indicated in the question. If such is required then you should add additional logic to handle such a case e.g. maybe modify the AskQuestions function to return false when its time to quit, in which case main might look like so:

   // Main: loops calling AskQuestions and WaitForFiveMinutes
   //       until AskQuestions returns false.
   int main()
   {
       while ( AskQuestions() )
       {
         WaitForFiveMinutes();
       }
   }

The code can be used on MS Windows systems by defining PLATFORM_IS_WIN32 or on systems with a POSIX style sleep function by defining PLATFORM_IS_POSIX. This can either be done in the code, e.g.:

   #define PLATFORM_IS_WIN32

Or on the command line e.g. by using a -D option:

   g++ thecode.cpp -Wall -o theprogram -DPLATFORM_IS_POSIX

or similar. In my case as I have MSVC++ on MS Windows Vista and GNU g++ on Ubuntu Linux available I used their respective compiler identification pre-defined macros to set the correct macro:

   #if defined(_MSC_VER)

   # define PLATFORM_IS_WIN32

   #elif defined __GNUC__

   # define PLATFORM_IS_POSIX

   #endif

However this is in no way a water tight method as g++ is available for many systems including Microsoft systems and of course they only cover these two compilers and there are many more that could be used - however it shows the very basics of such configuration techniques and will do for this simple example. Oh, and now we have 64 bit MS Windows versions and the Win64 API the PLATFORM_IS_WIN32 may be too narrowly named!

Other things that you may wish to look into are:

   - making the WaitForFiveMinutes function less specific - maybe it should take a
     seconds parameter and be renamed something like WaitSeconds
   - What happens if you wish to quit while waiting?
     Is there any cleanup to be done?
     Or can you safely just kill the process (e.g. with <ctrl>-C).
   - Should time taken to answer the questions be taken into account in the time waited?
     If so, what should you do if the user takes more than 5 minutes to answer?
     (maybe they went for a coffee break...)

Note that if you are building the above program then you may need to add libraries to the linker options.

If using MSVC++ you will need to have the platform SDK installed and setup for use with MSVC++ / Visual Studio and link with Kernel32.lib. Not all compilers targeting MS Windows systems come with (or have available) the Microsoft platform SDK. Specifically, the MinGW port of the GNU compiler (which is used by the DevC++ IDE) has its own versions for many Microsoft API header files and libraries (see http://www.mingw.org/).

For Linux and UNIX you will usually find that if you have a compiler available then you have the system header files and libraries installed. The GNU compilers are often provided in a configuration that includes linking by default with the C library (and C++ library for g++) including many Linux / UNIX system-only API functions. If something is not available then you (or someone else - e.g. the system administrator) may have to install the required packages or some such.

If you run into trouble or simply require more information then you will have to read the documentation for your compiler, linker, and system. For Microsoft this would be the MSDN library (see http://msdn2.microsoft.com/). For UNIX / Linux you should have the man - manual - pages available as a starter, so entering for example:

   man g++

as a console command would display the manual page for the GNU compiler - if it does not then someone may have to install additional documentation packages or similar.

Oh, and the Internet, and search engine sites such as Google, are your friend here - for example the man pages for most (all?) UNIX / Linux functions can be found online in various places, as can further informative articles. Tracking them down can be another issue however <g>!

If you are using a free standing C++ implementation then all the above is of no use to you. In such cases you will probably be writing code that interfaces to the hardware directly. In such cases you would have to set up your own timer functionality - possibly (probably) using hardware timer support. How to go about this of course depends on the hardware and the uses of it for the specific case in hand (maybe there is some code available already to make use of such facilities).

I hope this is of use to you. If you need something further or do not understand something in my answer then please do post another (possibly follow up) question. Finally, the code shown in the answer are for example purposes only to illustrate the points made in the text. They are in no way intended to be of production quality.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.