Question

In UIKit framework, there are methods associated with app’s life cycle events like applicationWillEnterForeground(_:) which are called at appropriate times.

How can I make a process receive such events from an operating system? If the operating system has to be programmed to be able to notify the processes of system events, how can it be done?

I have found that signals can be used but it is not usually used to transfer data. I read it here.

What I want to know is how a process can run certain block of code which may receive some data from the system when it enters background, enters full screen or the system has changed it’s theme such as a dark theme.

Was it helpful?

Solution

The operating system should not just start running the code in the process. That's been tried before (UNIX signals) and it didn't work very well - it's very difficult to handle signals without bugs.

Generically: The operating system provides some kind of "wait for something to happen" syscall. The application then has a main loop that looks like:

while(true) {
    thing = waitForSomethingToHappen();
    handleThingThatHappened(thing);
}

On Linux, most I/O is based on file descriptors. You use poll (or one of the related functions) to ask the kernel to pause your process until to wait until certain file descriptors have data available to read - or, less commonly, until they have space in the buffer to write.

while(true) {
    struct pollfd fds[] = {
        {fd_1, POLLIN}, // want to know if there's data to read from fd_1
        {fd_2, POLLIN}, // want to know if there's data to read from fd_2
        {fd_3, POLLOUT}, // want to know if there's space to write to fd_3
    };
    poll(fds, 3); // error handling skipped for demonstration
    if(fds[1].revents & POLLIN) readData(fd_1);
    if(fds[2].revents & POLLIN) readData(fd_2);
    if(fds[3].revents & POLLIN) writeData(fd_3);
}

A process can have many file descriptors and it tells the OS which ones it wants to wait for. You have to explicitly connect to things. If you want to draw stuff on the screen, you have to connect an FD to the X server (which manages the screen) and when it has something to tell you, it sends you some data, which you read and process. When your window becomes the foreground, the X server will tell you and it's up to you to respond.

On Windows, there are several different mechanisms, but the most familiar is the Windows message queue. You use GetMessage to wait for a message:

struct MSG msg;
while(GetMessage(&msg, 0, NULL, NULL) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

Unlike Linux, you only have one message queue per thread (but not every thread has a message queue). If you want to wait for something that's not a message - like I/O - you typically have to start a new thread to do it.

When your window becomes the foreground, a message magically arrives in the queue of the thread which created the window. You still don't receive it until you call GetMessage.

OTHER TIPS

First, the operating system has complete control of the computer. If it wants the app to do something it will do it.

The general mechanism specific to MacOS and iOS you are asking about is the Notification Center. Each application has an instance of the Notification Center. Your application registers code that it wants to be executed when some notification is received. The “springboard” process is part if the operating system, it both activates and deactivates processes and sends notifications to those processes as appropriate. It can do that because it is part of the OS and allowed to send notifications to other processes.

The OS will also call certain optional methods of the AppDelegate protocol if implemented.

Licensed under: CC-BY-SA with attribution
scroll top