iOS RunLoop(1)
function loop() {
initialize();
do {
var message = get_next_message();
process_message(message);
} while (message != quit);
}
일반적으로 이 모델을 Event Loop이라고 합니다.Event Loop은 많은 시스템과 프레임워크에서 이루어진다. 예를 들어 Node.js의 이벤트 처리, 예를 들어 Windows 프로그램의 메시지 순환, 그리고 OSX/iOS의 RunLoop.이러한 모델을 실현하는 관건은 이벤트/메시지를 어떻게 관리하는가, 정보를 처리하지 않을 때 자원 점용을 피하고 메시지가 왔을 때 즉시 깨어나게 하는가이다.
따라서 RunLoop은 사실상 하나의 대상이다. 이 대상은 처리해야 할 이벤트와 메시지를 관리하고 입구 함수를 제공하여 위의 Event Loop의 논리를 집행한다.루틴이 이 함수를 실행하면 이 함수 내부의 '메시지 수락 -> 대기 -> 처리' 순환에서 이 순환이 끝날 때까지 (예:quit에 전송된 메시지) 함수가 되돌아옵니다.OSX/iOS 시스템에는 NSRunLoop과 CFRunLoopRef라는 두 개의 객체가 있습니다.CFRunLoopRef는CoreFoundation 프레임워크 내에 있으며 순수 C 함수의 API를 제공합니다. 모든 API는 라인이 안전합니다.
RunLoop과 스레드의 관계는 우선 iOS 개발에서 두 개의 스레드 대상을 만날 수 있다. pthreadt 및 NSThread과거 애플은 NSThread가 pthread일 뿐이라는 문서를 표시했다.t의 봉인이지만, 그 문서는 이미 효력을 상실했습니다. 현재 그것들도 모두 맨 밑에 있는mach thread에서 직접 포장할 수 있습니다.애플은 이 두 대상이 서로 전환하는 인터페이스를 제공하지 않았지만, 어쨌든 pthreadt와 NSThread는 일대일로 대응한다.예를 들면, 당신은 pthread 를 통과할 수 있습니다.main_np() 또는 [NSThread mainThread]에서 마스터 스레드를 가져옵니다.pthread를 통해서도현재 스레드를 가져오려면 self () 또는 [NSThread currentThread] 를 사용하십시오.CFRunLoop은 pthread를 기반으로 관리됩니다.
애플은 RunLoop을 직접 만들 수 없습니다. 이것은 자동으로 가져오는 두 가지 함수만 제공합니다. 그것이 바로 CFRunLoopGetMain () 과 CFRunLoopGetCurrent () 입니다.이 두 함수 내부의 논리는 대략 다음과 같다.
/// Dictionary,key pthread_t, value CFRunLoopRef
static CFMutableDictionaryRef loopsDic;
/// loopsDic
static CFSpinLock_t loopsLock;
/// pthread RunLoop。
CFRunLoopRef _CFRunLoopGet(pthread_t thread) {
OSSpinLockLock(&loopsLock);
if (!loopsDic) {
// , Dic, RunLoop。
loopsDic = CFDictionaryCreateMutable();
CFRunLoopRef mainLoop = _CFRunLoopCreate();
CFDictionarySetValue(loopsDic, pthread_main_thread_np(), mainLoop);
}
/// Dictionary 。
CFRunLoopRef loop = CFDictionaryGetValue(loopsDic, thread));
if (!loop) {
/// ,
loop = _CFRunLoopCreate();
CFDictionarySetValue(loopsDic, thread, loop);
/// , , RunLoop。
_CFSetTSD(..., thread, loop, __CFFinalizeRunLoop);
}
OSSpinLockUnLock(&loopsLock);
return loop;
}
CFRunLoopRef CFRunLoopGetMain() {
return _CFRunLoopGet(pthread_main_thread_np());
}
CFRunLoopRef CFRunLoopGetCurrent() {
return _CFRunLoopGet(pthread_self());
}
위의 코드를 통해 알 수 있듯이 루틴과 RunLoop 사이에는 일일이 대응하고 그 관계는 하나의 전역적인 Dictionary에 저장된다.루프가 처음 만들어졌을 때 RunLoop이 없었습니다. 만약 당신이 주동적으로 가져오지 않았다면, 루프는 없었을 것입니다.RunLoop의 생성은 처음 가져왔을 때 발생했고, RunLoop의 삭제는 라인이 끝났을 때 발생했습니다.한 라인의 내부에서만 RunLoop을 얻을 수 있습니다. (주 라인을 제외합니다.)
RunLoop 외부 인터페이스
CoreFoundation에서 RunLoop과 관련된 5가지 클래스는 다음과 같습니다.
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
이 가운데 CFRunLoopModeRef류는 외부에 노출되지 않고 CFRunLoopRef의 인터페이스를 통해 봉인됐다.하나의 RunLoop은 몇 개의 모드를 포함하고, 각각의 모드는 몇 개의 Source/Timer/Observer를 포함한다.RunLoop의 주 함수를 호출할 때마다 그 중 하나만 지정할 수 있습니다. 이 모드는CurrentMode라고 부릅니다.Mode 를 전환하려면 Loop 을 종료하고 Mode 를 다시 지정해야 합니다.이렇게 하는 것은 주로 서로 다른 그룹의 Source/Timer/Observer를 분리하여 서로 영향을 주지 않도록 하기 위해서이다.CFRunLoopSourceRef는 이벤트가 발생하는 곳입니다.Source에는 Source0과 Source1의 두 가지 버전이 있습니다.Source0은 하나의 콜백(함수 포인터)만 포함하고 이벤트를 자발적으로 트리거할 수 없습니다.사용할 때, CFRunLoop Source Signal (source) 을 호출해서 이 Source를 처리할 것으로 표시하고, 이 사건을 처리할 수 있도록 CFRunLoop Wake Up (runloop) 을 수동으로 호출해야 합니다.Source1에는 mach 이 포함되어 있습니다.port와 리셋 (함수 바늘) 은 내부 핵과 다른 라인을 통해 서로 메시지를 보내는 데 사용됩니다.이런 Source는 RunLoop의 라인을 자발적으로 깨울 수 있는데 그 원리는 아래에서 설명할 것이다.CFRunLoopTimer Ref는 시간 기반 트리거로 NSTimer와toll-free bridged로 혼용할 수 있습니다.그것은 시간 길이와 리셋을 포함한다.RunLoop에 가입하면 RunLoop은 해당 시점을 등록하고 해당 시점이 되면 RunLoop은 해당 콜백을 수행하기 위해 깨어납니다.
CFRunLoopObserverRef는 관찰자로서 모든 Observer에는 리셋(함수 바늘)이 포함되어 있으며 RunLoop의 상태가 변할 때 관찰자는 리셋을 통해 이 변화를 받아들일 수 있다.관측 가능한 시점은 다음과 같습니다.
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // Loop
kCFRunLoopBeforeTimers = (1UL << 1), // Timer
kCFRunLoopBeforeSources = (1UL << 2), // Source
kCFRunLoopBeforeWaiting = (1UL << 5), //
kCFRunLoopAfterWaiting = (1UL << 6), //
kCFRunLoopExit = (1UL << 7), // Loop
};
위의 Source/Timer/Observer는 모뎀 item이라고 통칭하는데 하나의 item은 여러 모뎀을 동시에 추가할 수 있다.그러나 하나의 item이 같은 모델을 중복적으로 추가할 때 효과가 없습니다.모드에 item이 없으면 RunLoop은 순환에 들어가지 않고 종료됩니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.