실행기 다시 보기
콜백 하나가 오래 걸리면, 다른 콜백은 어떻게 될까?
실행기
콜백을 부르는 쪽은 실행기입니다
6강 3편에서 rclpy.spin(node)이 콜백을 꺼내 부른다고 했습니다. 그 일을 하는 것이 실행기(executor)입니다. 메시지 도착, 타이머 시간, 서비스 요청 같은 일이 생기면 실행기가 짝이 되는 콜백을 부릅니다.
액션 서버·클라이언트의 콜백도 실행기가 부릅니다(9강).
spin의 속
rclpy.spin은 실행기 하나를 돌립니다
rclpy.spin(node)은 기본 실행기인 SingleThreadedExecutor에 노드를 넣고 돌립니다. 아래처럼 직접 만들어 add_node로 노드를 넣고 spin()을 불러도 같습니다.
이름 그대로 스레드 하나로 콜백을 부르는 실행기입니다.
기다리는 곳
메시지는 콜백이 꺼낼 때까지 미들웨어에 있습니다
도착한 메시지는 콜백이 꺼내 갈 때까지 미들웨어 쪽 대기열에 머뭅니다. 3편의 Depth가 바로 이 대기열 크기입니다. 실행기는 어느 대기열에 "할 일이 있다"는 표시만 보고, 하나씩 꺼내 콜백을 부릅니다.
이 표시를 모아 기다리는 장치를 wait set이라고 합니다.
한 줄로
스레드 하나는 한 번에 하나만 부릅니다
SingleThreadedExecutor는 콜백을 차례로 하나씩 부릅니다. 한 콜백이 오래 걸리면, 그동안 시간이 된 타이머 콜백도 기다려야 합니다. 그래서 콜백 안에서는 오래 걸리는 일을 피하는 것이 좋습니다.
노드 여럿
실행기 하나에 노드 여럿도 됩니다
한 프로그램 안에서 노드 둘을 같은 실행기에 넣을 수 있습니다. 이때 스레드 하나가 두 노드의 콜백을 모두 차례로 부릅니다. 실행기는 노드보다 한 층 바깥에서 콜백을 나눠 부르는 일꾼입니다.
talker, listener는 예시로 만든 노드 객체 이름입니다.
주의
콜백 안에서 기다리면 멈춥니다
7강 7편의 함정이 여기서 생깁니다. 콜백 안에서 서비스의 동기 call()로 답을 기다리면, 답을 받아 줄 콜백도 같은 스레드를 써야 해서 영원히 차례가 오지 않습니다. 그래서 콜백 안에서는 call_async와 add_done_callback을 씁니다.
콜백 안에서 spin_until_future_complete를 부르면, 버전에 따라 멈추거나 RuntimeError: Executor is already spinning 오류가 납니다.
다음 편