작업 완료를 알리는 데 dispatch_semaphore_t를 사용하고 있습니다. 세마포어가 멤버 변수 인 경우 제대로 작동하지 않는 것처럼 보입니다. 내 실제 코드에 설명 된대로 가지고, 나는 중단 점을 넣어/그 코드 내가 얻는 결과를 제공, 그래서dispatch_semaphore_t reuse - 내가 무엇을 놓치고 있습니까?
@implementation someClass
{
dispatch_semaphore_t memberSem;
dispatch_semaphore_t* semPtr;
NSThread* worker;
BOOL taskDone;
}
- (id)init
{
// Set up the worker thread and launch it - not shown here.
memberSem= dispatch_semaphore_create(0);
semPtr= NULL;
taskDone= FALSE;
}
- (void)dealloc
{
// Clean up the worker thread as needed - not shown here.
if((NULL != semPtr) && (NULL != *semPtr))
disptatch_release(*semPtr);
dispatch_release(memberSem);
}
- (void)doSomethingArduous
{
while([self notDone]) // Does something like check a limit.
[self doIt]; // Does something like process data and increment a counter.
taskDone= TRUE; // I know this should be protected, but keeping the example simple for now.
if((NULL != semPtr) && (NULL != *semPtr))
dispatch_semaphore_signal(*semPtr); // I will put a breakpoint here, call it "SIGNAL"
}
- (BOOL)getSomethingDoneUseLocalSemaphore
{
taskDone= FALSE; // I know this should be protected, but keeping the example simple for now.
dispatch_semaphore_t localSem= dispatch_semaphore_create(0);
semPtr= &localSem;
[self performSelector:doSomethingArduous onThread:worker withObject:nil waitUntilDone:NO];
dispatch_time_t timeUp= dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(2.5 * NSEC_PER_SEC));
dispatch_semaphore_wait(localSem, timeUp);
semPtr= NULL;
dispatch_release(localSem);
// I know I could just return taskDone. The example is this way to show what the problem is.
if(taskDone) // Again with thread safety.
return TRUE;
return FALSE;
}
- (BOOL)getSomethingDoneUseMemberSemaphore
{
taskDone= FALSE; // I know this should be protected, but keeping the example simple for now.
semPtr= &memberSem; // I will put a breakpoint here, call it "START"
[self performSelector:doSomethingArduous onThread:worker withObject:nil waitUntilDone:NO];
dispatch_time_t timeUp= dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(2.5 * NSEC_PER_SEC));
dispatch_semaphore_wait(memberSem, timeUp);
semPtr= NULL;
// I know I could just return taskDone. The example is this way to show what the problem is.
if(taskDone) // Again with thread safety.
return TRUE; // I will put a breakpoint here, call it "TASK_DONE"
return FALSE; // I will put a breakpoint here, call it "TASK_NOT_DONE"
}
- (void)hereIsWhereWeBringItTogether
{
BOOL gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore]; // Will return TRUE.
gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore]; // Will return TRUE.
gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore]; // Will return TRUE.
BOOL gotItDoneMember= [self getSomethingDoneUseMemberSemaphore]; // Will return TRUE. I will put a breakpoint here, call it "RUN_TEST"
gotItDoneMember= [self getSomethingDoneUseMemberSemaphore]; // Will return FALSE.
}
을 : 나는 예를 들어 작동 코드와 작동하지 않는 예를 보여줍니다에 하나 main 함수, 작업 함수에서 시작하는 멤버 함수, 멤버 세마포어가 신호를받는 함수 및 대기 후 2 매개 변수
멤버 세마포어를 사용하는 경우 첫 번째 라운드에서 중단 점 "RUN_TEST"에서 멈추고 "START"를 실행하고 중단 점 "SIGNAL"을 실행 한 다음 중단 점을 눌러 실행합니다. "TASK_DONE"- 모두 예상대로입니다.
나는 계속 실행
, 나는, 실행 후 나는 인 세마포어를 사용하여 순서를 실행할 때, 중단 점 "신호"충돌 중단 "START"를 실행 한 다음 "TASK_NOT_DONE을"중단 점에 명중 멤버, 적절한 시그널/기다림처럼 보입니다. 두 번째로 세마포어를 기다리려고합니다. 나는 그걸 기다렸다가 신호를받습니다.
나는 카운팅 권한 (신호/대기 쌍)을 관리하지 않거나 멤버 세마포어가 신호되지 않은 상태로 돌아 가지 않을 것 같습니다.
내 느낌에는 여기에 실종 된 근본적인 것이 있습니다. 모든 입력을 부탁드립니다.
편집 : 궁극적으로 내가 실종 된 것으로 보이는 것은 실제 코드가 좀 더 복잡하기 때문입니다. 힘든 작업에서 깨끗한 반환 대신에, 관련된 여러 스레드 및 postNotification 있습니다. postNotification을 알림 처리기의 코드로 바꿨습니다. 플래그를 설정하고 세마포 신호를 보냅니다. 이렇게하면 알림 핸들러에서 도입 된 지연이 제거됩니다.
무슨 뜻인지 알 겠어. 기본적으로 작업이 대기보다 오래 걸리면 대기 시간이 초과되지만 신호는 계속 카운터를 증가시켜 다음 대기가 즉시 시작됩니다. 그것은 제가 생각한 것입니다. 그러나이 경우 분석기를 연결하여 잠시 후에 작업이 완료되는 것을 볼 수 있습니다. 나는 세마포어가 단지 기다리기 전에 * 신호를 받는지 테스트 할 수 있다고 생각한다. * 나는 오래 전에 프로세스를 시작했다. 시간 초과되지 않으면 계속 진행되고 있으며 대기 시간을 적절하게 조정할 수 있습니다. – GTAE86
@ GTAE86 수정. BTW, 지역 세마포어 코드를 설정 한 방법은 이론적으로 멤버 변수 예제와 동일한 동작을 계속 볼 수 있습니다 (정확한 타이밍의 문제임). 어떤 인스턴스 변수에서 세마포어를 선택하는 것보다 (심지어 현재의 "로컬 변수"예제가 인스턴스 변수에 세마포어 저장을 끝내는) 다양한 작업의 다양한 신호 사이에 혼선을 원하지 않는다면, 세마포어를 매개 변수로 전달하거나 인스턴스 변수를 사용하지 않도록합니다 (또는 각 작업에 대해 객체의 별도 인스턴스를 만듭니다). – Rob
내 코드에서 무슨 일이 벌어지는지를 볼 수 있습니다. 여러 스레드가 실행 중입니다 (예제보다 더 복잡합니다).힘든 과정은 다음과 같습니다 스레드에서 장치에 쓸 대기 스레드 B를 기다립니다. 스레드 C는 응답 (ReadPipeAsync)을 받고 양키 (deque)에 캐시합니다. 스레드 D는 분석을 위해 스레드 D를 뽑습니다. 좋은 경우 결과와 함께 알림을 게시합니다. 알림 처리기는 일부 검사를 수행하고 완료 상태 (잠금으로 보호되는 변수로 설정 됨)를 요청하고 요청 된 경우 세마포어에 신호를 보냅니다. 내 작업이 빨리 완료되었다는 것을 알지만 그 알림은 지연 될 수 있습니다. – GTAE86