-3

I am try to implement a periodic event in C++, on an embedded device with limited library functions available. I cannot use sleep or other delays since it stop the current execution.

For eg.

do
{
    if(something)
    {
       //Do something
    }

    if(something)
    {
       //Do something
    }

    if(every 5 minutes)
    {
       //Do something only once after 5 minutes
    }
}
while(true)

I am not sure how to go about this. Can you help me with this since I need to implement this in this do while loop? I would have used threads, but on this device that's not really possible, so I'm looking for another way.

Jason C
  • 38,729
  • 14
  • 126
  • 182
RDoonds
  • 485
  • 2
  • 6
  • 19
  • 6
    If there only was a way to get the current time inside a loop ... – Jongware Aug 24 '16 at 22:40
  • 4
    Are you running this on a POSIX system? You can use `alarm()` to send a signal after 5 minutes, and the signal handler will do what you want. – Barmar Aug 24 '16 at 22:42
  • Or, at a push, hatch a `std::thread` and `sleep` on that. But only if desperation takes hold — threads aren't free. – Tommy Aug 24 '16 at 22:43
  • 1
    You might want to set up an event loop here, or use an off-the-shelf one like [libuv](http://libuv.org) which gives you a lot of timer functionality. – tadman Aug 24 '16 at 22:43
  • @RadLexus , this isn't a joking matter - these `time` system calls are expensive to perform... :-p ...and signal handlers such as the ones used with `alarm` are notoriously tricky. Even timer event polling using `epoll` or `kqueue` with a timer `fd` are full of requirements... seriously, what is a performance oriented programmer to do? – Myst Aug 24 '16 at 22:44
  • @Myst: well, OP ruled out using the obvious solution: threads. That leaves very few options. – Jongware Aug 24 '16 at 22:46
  • Oh, you're right. So he wants not to move execution outside of a single do/while loop, but also for execution not to be blocked while waiting for the event to happen? – Tommy Aug 24 '16 at 22:47
  • 1
    @RadLexus , I'm happy you like my humor :-) – Myst Aug 24 '16 at 22:48
  • I have attempted to salvage this question, and have voted to reopen. I think it is useful now in its current form. Also, fwiw, too broad was not the appropriate close reason. Unclear was. Please don't blow through review queues! – Jason C Aug 25 '16 at 16:20
  • Without further information, an answer is impossible. If that is some bare-metal MCU, timers and interrupts are an option. Possibly an RTOS with timer-tasks. None is simple for a beginner, but you might find information by some **research on your own**. – too honest for this site Aug 25 '16 at 23:22
  • Crazy idea - can the program be split up using OpenMP or manual subdivision? Even without an RTOS, separate processes can run concurrently without explicit use of threads. – John P Aug 29 '16 at 15:34

2 Answers2

3

Well, of course, the advice to spawn off a separate thread (that's what I would do) or use alarm() given in the comments is good advice, but may not be possible on your device. However, focusing on your current approach, generally the idea is, pseudo-code:

last action time = current time

while (true) {
   do things.
   if current time - last action time >= 5 minutes then
       perform action
       last action time = current time
       // or last action time += 5 minutes if you want to mitigate drift
   end
}

So now you just need to pick your favorite way to get the current time. On a desktop platform you could use e.g. time(), gettimeofday(), GetTickCount() on Windows, etc. Some embedded platforms may provide those as well. However, this could be problematic:

Since you mentioned in a comment that you are working on an embedded device, "your favorite way to get the current time" will vary depending on the platform, you'll just have to check the device docs. If you're lucky, your MCU may provide a way to query the CPU counter, and the frequency you usually know already from your setup. But it may not.

If it does not, another alternative is if your device provides an on-board timer. In this case, you may be able to configure it and respond to periodic interrupts, in that case your two options are generally:

  1. Do the action in the timer interrupt handler - but only do this if it's short, and you take proper precautions for interrupt-safety.
  2. Set a volatile flag in the timer interrupt handler, check that flag in the main loop and execute the action + reset the flag there if it is set. This is generally a much simpler approach.

Doing it that way is architecturally similar to using alarm(). However, there are certainly embedded platforms that implement time() and/or gettimeofday() as well. But those are your choices.

Jason C
  • 38,729
  • 14
  • 126
  • 182
  • 3
    @Myst I always just figure some people don't like the fact that my avatar incorrectly portrays a giraffe as having a short neck. – Jason C Aug 24 '16 at 22:50
  • Not my DV, but I don't think this is a good answer. Actually the question is not good, too and far too broad. "Most MCU's provide a way to query the CPU counter and the frequency. " - is plain wrong. Hardly any MCU with less than 32 bits even has a CPU-counter (whatever that might be -1 CPU, 2 CPUs?) and almost none has a way to query the frequency - how would it without a defined 2nd reference clock? – too honest for this site Aug 25 '16 at 23:25
  • @Olaf Yeah the question is dubious. I tried, but you know what they say, can't polish a turd. As for the answer, I will change "most" to "some ... may", and hopefully that will put your soul at ease and let us move past this great tragedy. Hopefully there is at least some redeeming quality in the *rest* of my answer besides that single qualitative word, but I completely understand how that may have invalidated the entire thing. (Amusingly, when I wrote "most" to begin with I thought, "maybe I should change that... nah, surely any reader with a brain will be able to get the point here"). – Jason C Aug 25 '16 at 23:29
0

This sounds like you're looking for two different capabilities; one, to dispatch a command without disrupting execution; two, to wait for a certain amount of time. For the first, you're looking for asynchronous programming. For the second, I recommend Boost::deadline_timer. To combine the two, look at Boost::io_service, which will allow you to register asynchronous callbacks with or without the use of a timer.

John P
  • 1,463
  • 3
  • 19
  • 39
  • I cannot use boost since its very large and occupies lots of space. I am working on embedded device where I have storage limitation – RDoonds Aug 24 '16 at 22:49
  • 2
    @RDoonds Did you not feel that that would have been useful information to mention in your question? o.O – Jason C Aug 24 '16 at 23:05
  • Boost can be embedded just fine, as far as I know. http://stackoverflow.com/questions/166542/using-boost-in-embedded-system-with-memory-limitation – John P Aug 24 '16 at 23:24
  • In any case, io_service and deadline_timer are only recommendations. Asynchronous dispatches with variable delays are your best bet. What are you using for threading? What are your other constraints, if any? Maybe I can still help. – John P Aug 25 '16 at 18:36
  • Wait, you aren't using threads but you don't want to stop execution? Just count time elapsed and execute if you meet your threshold. You're out of luck if any of the calls take too long or fail to return; if possible, use some form of coroutine, partial result, or timeout to mitigate this risk. – John P Aug 25 '16 at 18:46