My question is about the construction of main loops running in the background listening to commands and signals and how are they constructed to be efficient. For instance in live music synthesis programming languages like SuperCollider or PureData, you have somewhere a sound server waiting for changes in your source code and applying changes immediately to your program. Are these things like simple while loops running for ever, waiting for updates in the environments. Running a simple while loop in python will consume more than half of the CPU, so this can surely be not done. Can any one give me some hints?


This is highly operating system specific. Read about event loops.

On Linux and other POSIX systems, event loops are coded around a multiplexing system call such as poll(2), or the older select(2), etc (see epoll(7) ...) etc... In Python, see its selectors module.

you have somewhere a sound server waiting for changes in your source code

That reminds me of inotify(7) (on Linux).

In all cases, you'll use operating system specific services provided by your OS kernel. For Linux, see its syscalls(2). For Windows, dive into its WinAPI. In general, read Operating Systems: Three Easy Pieces.

BTW, SuperCollider is free software, so you should study its available source code.


There are two fundamental approaches to handling externally generated commands and signals: polling and handlers.

Polling involves looping until some condition is reached.  When doing polling, condition testing can be non-blocking so that the polling code can go on to test other conditions, and then loop to repeat.  This approach can be used by programs hosted by an operating system, and also, by a main program running without an operating system, such as on micro-controllers (like Atmel AVR).  You are correct that this can be a very inefficient use of cycles.  For operating system hosted computers, this matters, for a micro controller it may not matter since there is nothing else for the processor to do (and they are already low power consumption).

Code doing IO can also use a blocking approach (called blocking IO or to some just program IO) to testing conditions and/or accomplish IO transfer, which means the the program is suspended (the calling thread) until such event occurs (or times out).  Blocking IO is a concept that an operating system constructs though composition of processor interrupt handlers and scheduling (i.e. program/thread suspend/resume).  Blocking IO does not require a loop to accomplish an IO operation — but, of course, is often used in a loop to do repeated IO operations.

Blocking IO has both pros and cons.  As for pros, blocking IO generally consumes no CPU cycles during waiting, instead returning control of the CPU to the operating system to use as needed.  For cons, blocking IO blocks, so the program becomes non responsive while waiting for blocking IO (beyond using handlers, a program/thread that does blocking IO can use timeouts or multiple threads to keep itself otherwise alive and/or responsive).

Operating systems on older hardware required a notion of an idle loop or idle process.  In a well-constructed operating system, the idle loop will run only when all other parts of the system (e.g. programs and kernel) are waiting for external IO events.  Modern hardware has a notion of explicit wait instructions, that do the equivalent of the idle loop while also triggering a lower power-consumption processor state (which is exited on external interrupt).

Handlers involve registration of some code with a service of some sort that in turn will invoke the handler in response to certain classes of events.  Handlers registered at the processor level are called interrupt service routines.  (User level) handlers registered with the operating system can be called signal handlers or event handlers.

The two approaches of polling and handlers can be mixed, e.g. at different levels in the software stack.

For example, a modern operating system would use interrupt handlers registered directly with the hardware — these handlers run in response to certain classes of external events, which includes data being received from a keyboard, network card, disc, etc... Exactly how the data is transferred is device specific but could involve io ports, or memory mapped io perhaps via Direct Memory Access by the device.  The operating system then hosts programs, which can use event handlers, non-blocking IO, and/or blocking IO (and threads).  Of course, programs can dynamically spawn/launch (or kill and relaunch) other programs.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.