Quantcast
Viewing all articles
Browse latest Browse all 4954

C/C++ • Re: Timers in C++

@swampdog

I certainly misunderstand a lot of things, not only threads. To answer a couple of your questions: it would be a GUI program, part of a control system where the user can set some configuration parameters, among others timers, and the program will, among other things, switch things on and off at the times given by those parameters.
Think like: fan1 has to be on for t1 and then off for t2, light1 has to be on for t3 and then off for t4, motor1 has to run for t5 in one direction, for t6 in the other direction and then change direction again, and so on. The timing doesn't have to be awfully accurate: a drift of a few hundredth of a second are not a problem.
The things I found are quite a few, for instance this https://stackoverflow.com/questions/109 ... mer-in-c-c or this https://www.fluentcpp.com/2018/12/28/timer-cpp/.

Like you said, I don't understand much about threads (or about anything else, for that matter, I haven't even started coding anything yet, so you can't even call me a beginner Image may be NSFW.
Clik here to view.
:D
), but if the idea I get by reading these is correct:

- Take the thread for the fan, for instance. It would have to run forever, waiting (sleeping for) t1, then switching the fan off, sleep for t2 then switch the fan on and looping like that forever. This thread will never return until someone pushed the "off" button. With my poor understanding of the thing, if I start having a lot of timers that all work this way, I may run out of CPU cores and the OS would have to schedule them somewhat funny, thereby kicking the "timing" function of them to the moon (not really, I expect the drift to still be acceptable, but I guess you understand what I mean).

- Another way I see is having two threads: one that switches the fan on and one that switches it back off. That way the threads would return each time, thereby freeing their resources, but the "main" would have to take care to call the "fan on" and "fan off" functions and send them to a thread in rapid succession. If it's busy doing other things, there could be some delay and, again, the timing could end up being too much off (not for my purpose, I expect, but for a general useful function of timers).

As ttapa said:
That said, using an entire thread just to put it to sleep is rather wasteful.
Another possibility I thought of, and this is the reason of my question to start with, is taking the time when something starts, like the fan goes on, and compare it at each cycle of the program with the current time. If t1 has elapsed, switch the fan off, otherwise keep going through the rest of the instructions. Of course that too isn't very accurate as a timer, because there's no telling how long the program will take to complete one round and start from the beginning, but at least it would save me the trouble of thread programming.

I would be glad to stand corrected on the above, if that is not the way it works, as I like to learn (and I'm just starting). In the meantime I'll look into that ASIO stuff. Thanks for the lead.

If anyone has a better idea...
Bit of history:
The problem with threads is they've been around for since the dawn of time (in some form) but there isn't a standard way to use them. In C++ as @deepo shows they're making an attempt to the extent the language has a concept of a thread. Threads only exist because actual processes typically can't communicate with each other fast enough. If we ignore the comparatively massive waste of resources involved when two processes try to communicate, threads are the same as processes (in a multitasking OS). We all assume "pre-emptive" multitasking these days. It hasn't always been that way - "cooperative multitasking" was a thing: that was when the OS would only appear to be running more than one program at once because each program would cooperate by periodically making an OS call which would allow the OS to suspend the current process and move to the next process. If a program didn't do that then that program got to hog the cpu forever. It can be argued cooperative multitasking was a fudge to make the first GUI programs look more fluid: the OS would be unable to (re)draw the display if a process was busy doing something intensive. Imagine a process was loading a large file which might take many (tens of) seconds - the desktop would appear to freeze until that was complete. They only way around this was for the programmer of the process which loaded that large file to change their code so that the large file was loaded in small chunks, with a call to the OS between each chunk. Who's going to bother doing that for (say) a text editor which is normally only expected to load small files but the user has the editor load a huge one. Plus, changing code to do it in chunks introduces more potential for bugs. Pre-emptive multitasking does away with this (in theory) because the OS snatches control away from each process and will hand it to another process without the process being aware. I say "in theory" because there are certain operations which cannot be "pre-empted". That depends on the OS and is basically the reason why it's been impossible to concoct a standard thread until comparatively recently (because it requires leaving older OS behind).

A GUI needs two threads. One for "main" and one for the GUI to update/(re)draw the display. Each GUI implements its scheme on top of whatever OS it's built to support. Windoze for instance, has the concept of a "fibre". Have a glance at https://learn.microsoft.com/en-us/windo ... ing-fibers for an example of how silly things can get (then forget you ever saw it). This two thread things for GUI's should have been standardised decades ago but I hope I've waffled enough to give an idea of why it hasn't been happening until now.

I haven't mentioned the real problem with threads. That's getting them to talk. If you've got a variable one thread needs to read and another thread is writing that variable you need a mechanism to make that work. Google "mutex" to go down the rabbit hole. You need a mechanism to prevent one thread being midway through updating a variable at the same time another is trying to read it. This is known as an "atomic" operation. It either wholly succeeds or it wholly fails (like it never happened). At a higher level it's the same as a database transaction - you'd not want two different shops posting their debit on your bank account at the same time. One transaction has to wholly succeed (or fail) before the next one is allowed to happen. GUI's have to implement a solution for this.

The Atari ST (for instance) solved this via a message pump. Each app (process) would sit in a "while(true)" loop constantly making a GUI OS call and take actions based upon what messages it received. This would be down at the level of "mouse button pressed" or "timer" or redraw part of the display.

Windoze implements a callback mechanism where your app registers itself with the OS, which messages it wants to be told about, the end result being certain functions in your app may or may not get called.

Lots of variants for linux. The only one I know anything about is QT. It implements what is known as a "signal/slot" mechanism, basically a callback like windoze. You can design a menu or a dialog box then point objects at functions. eg: if you drop an "Ok" button object onto a form you can click on it to view its properties and (qtcreator) will create an empty function which will be called if the user clicks the Ok button. Ditto for other objects. Qt has timer functions and so forth which hide the OS details. It is cross-platform in case that matters. The complexity with Qt is the myriad of ways to use it and the abstraction levels. It has objects which are effectively "notepad" and then some. Provided you don't actually need resolution down to hundredths of second, it could suffice and possibly without even needing to use threads at all in the first instance (or even at all). Your "main" loop would do nothing (basically be asleep) until someone clicked on the "fan" button. Qt would call the function registered to pressing that button. All your code in that function would have do is "is fan is on then turn it off else turn it on" - and call the function you wrote which takes the associated gpio pin low/high to do it.

Periodically a QTimer event would wake your app up at which point it could decide if anything else needs to be done. You don't actually need a thread at all. Image may be NSFW.
Clik here to view.
;-)



I'm assuming it's not for the pico now.

Statistics: Posted by swampdog — Thu Dec 12, 2024 10:45 pm



Viewing all articles
Browse latest Browse all 4954

Trending Articles