Following up on the last blog post

RunLoop(1)

The state of the RunLoop

First let’s go to the source code of RunLoop to check it has several states, as shown below:

It has all of these states up here

/* Run Loop Observer Activities */

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

KCFRunLoopEntry = (1UL << 0), // About to enter loop

KCFRunLoopBeforeTimers = (1UL << 1), // Timer is about to be processed

KCFRunLoopBeforeSources = (1UL << 2), // About to process source

KCFRunLoopBeforeWaiting = (1UL << 5), // about to go to sleep

KCFRunLoopAfterWaiting = (1UL << 6), // Just woke up from sleep

KCFRunLoopExit = (1UL << 7), // About to exit loop

KCFRunLoopAllActivities = 0x0FFFFFFFU // All modes

};

C: C: C: C: C: C: C: C: C: C: C: C: C: C

From the result of the execution, it is exactly this many. The click event is executed at source0, so it is also clear from the log,

We know that kCFRunLoopBeforeWaiting is sleep, and kCFRunLoopAfterWaiting is sleep.

From the output, it does wake up. Perform block

Prove that mode switching exits RunLoop and re-enters RunLoop

We can easily prove this result from the surveillance above, right? Let’s take a look at the code, this time using another method of creating Observe described above, as shown below: Create a random view that can scroll, such as the Scrollerview I created.

When scrolling, we can obviously see the two modes switching, and RunLoop also needs to exit and re-enter to switch to the new mode.

In-depth understanding of the RunLoop execution process

Because the source code is abstract, it is pure C language, unlike our previous C ++ source code is easier to understand a little bit, so how do we find RunLoop function start? We know that clicks are also handled by Runloop, so we can look directly at the function call stack of click events to see the entry point.

It is clear from the above code that the CFRunLoopRunSpecific function is called. So let’s go to source search and this code is very easy to find. Take a look below:

A look at the source, we find that performed very much, you see if there is lock, green with multithreading, and so on, so we don’t have to study very thoroughly, a waste of time to also have no meaning, we just took roughly process le shun, so as long as we look at the key code, we’re going to see I only show the key code is as follows:

Next we go to see __CFRunLoopRun source code in the end what operation, the following source code is MY streamlined, we can refer to the source code to see, because there are many things, we do not need to understand all, as long as we know its execution process. See the picture below:

If the condition is not true, the return value will be set and the RunLoop will exit. Let’s summarize the process in words as follows:

Put another one in text:

This and the source code is basically the same process, you can refer to the source code or more abstract

Now let’s do one more thing.

What is executed in __CFRunLoopDoBlocks, __CFRunLoopDoObservers, and __CFRunLoopDoTimers

Observers, for example, __CFRunLoopDoSources0, are astounded at what they do, including blocks,timers, and observers:

In fact, the final treatment is this:

__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__

Let’s take a look at one of the previous screenshots

The above two functions are identical, further proving that the touch event is handled by source0.

Timers are the same, you can try it yourself.

What exactly does it mean to understand thread sleep?

RunLoop thread sleep is true sleep, it does not take up any CPU resources, completely rest. It is fundamentally different from White (1), which is running all the time. When it is converted to assembly, there will be several instructions. It is running all the time and consuming CPU resources. This is where the source code is located:

It’s going to execute the current code, it’s not going to go down, it’s not going to execute the next code, it’s going to get stuck, and once somebody wakes it up, it’s going to go down. We might wonder how does it do this dormancy?

So let’s take a look inside and see how this works, but it’s actually a function that executes a very kernel function called mach_msg, so can we take a look

Actually IPA can be divided into the kernel level of IPA: it is very, very bottom, is the operating system level, it allows a thread to sleep, also is really sleep, do not take up any CPU resources, is not open to our programmers use, because is the kernel, are more likely to programmers use dangerous, and the application layer to the IPA, are network request Page what.

So mach_msg, we can answer this function in the interview.

RunLoop hibernation implementation principle

It is the switch between user mode and kernel mode. User mode sends messages, kernel mode sleeps, wakes up, and user mode processes messages.

So if an interviewer asks: What about thread blocking in RunLoop? We mustn’t answer. It’s a loop. Those are the ones I just mentioned.

RunLoop and NSTimer story

We believe that the number of times encountered in development is very much, here is a brief mention.

For example, there are two common mode modes

1.KCFRunLoopDefaultMode (NSDefaultRunLoopMode): the default Mode of App, usually the main thread runs in this Mode

2.UITrackingRunLoopMode: interface tracking Mode, used for ScrollView tracking touch sliding, to ensure that the interface sliding is not affected by other modes

When adding a Timer to a runloop, we simply pass in the NSRunLoopCommonModes.

Let’s talk about the reason.

Let’s look at the structure of RunLoop from the last blog:

NSRunLoopCommonModes are passed in, which means that the timer can work with the modes in the _commonModes array. Notice NSRunLoopCommonModes this is not a mode.

The _commonModeItems store items that can work in _commonModes, such as the timer.

I’m going to continue with thread survival.

If you find my writing helpful, please follow me and I will continue to update 😄