19.5.3.2. px4::WorkItem 클래스 상속을 통한 이벤트 드리븐(Event-driven) 구독자 설계
백그라운드로 24시간 실시간 회전하는 거대한 ’글로벌 시스템 워크 큐(Work Queue)’에 내 코드를 무사히 태워 보내기 위해서는, 내가 작성한 코드 조각 블록은 OS 커널이 해석하고 이해할 수 있는 철저히 규격화된 스케줄링 티켓인 px4::WorkItem (또는 그 파생 객체들) 인스턴스로 안전하게 포장(Boxing)되어야만 한다.
PX4 프레임워크 코어 시스템은 이 스펙을 맞추기 위해, 모듈 개발자가 C++ 단에서 반드시 ModuleBase와 함께 px4::ScheduledWorkItem 기저 클래스를 다중 상속(Inheritance)받아, 자신만의 완전한 객체 지향 커스텀 데몬 클래스를 설계하도록 그 아키텍처를 강제하고 있다.
1. px4::WorkItem 파생 클래스 상속 아키텍처 타설 통제
우리가 지금까지 19.4.x 단원들을 치열하게 뚫으면서 짜 왔던, 가장 절망적으로 꼬질꼬질했던 로컬 main() 무한 루프 함수(while) 기반의 C 스크립트들은 이제 100% 모조리 폐기 처분한다. 그 자리에, 진정한 C++ 모던 프레임워크 위에서 단발성으로 숨 쉬고 기동하는 오만하고 우아한 이벤트 드리븐(Event-driven) 객체 지향 구조를 뼈대부터 다시 강력히 타설해 보자.
#include <px4_platform_common/module.h> // 기본 모듈 명령줄 파싱을 위한 ModuleBase 코어 헤더
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp> // WorkItem 백그라운드 스케줄링 코어 헤더
#include <uORB/SubscriptionCallback.hpp> // VFS 폴링 로직의 잔혹한 코드를 지워버리는 궁극의 콜백 자동화 래퍼 헤더
// 1. [다중 상속의 십자가] ModuleBase와 ScheduledWorkItem을 동시에 부모로 상속받는 마스터 워커 클래스 레이아웃 선언
class SensorSubscriber : public ModuleBase<SensorSubscriber>, public px4::ScheduledWorkItem
{
public:
// 2. 생성자 타설: 내가 이 시스템에서 평생 올라탈 고유 글로벌 큐의 이름(wq_hp_default)을 부모 클래스 스케줄러에 상납 등록한다.
SensorSubscriber() :
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::hp_default)
{
}
// 3. [핵심] 커널 큐가 내 스레드를 후려치며 인터럽트가 터졌을 때 유일하게 호출되어 실행될 팝업 콜백 함수 (명시적 Override 강제)
// - 더 이상 무한 루프가 없다. 데이터가 들어왔을 때 오직 이 함수 몸통 한 번만 딱 실행되고 데몬은 다시 동면한다.
void Run() override;
private:
// 4. [궁극의 객체 지향 래퍼] 기존의 더럽고 귀찮은 fd, px4_poll 구조체 배열 타설 로직을 모조리 C++ 은닉화로 숨겨버린 uORB 멀티플렉싱 콜백 객체
// 이 객체 덩어리는 백그라운드에서 스스로 VFS 링 버퍼망을 감시 카메라처럼 노려보다가, POLLIN 엣지가 터지면
// 그 즉시 이 클래스 자체를 큐에 밀어 넣어 Run()의 단발성 실행을 무자비하게 예약(Schedule)해버린다.
uORB::SubscriptionCallbackWorkItem _sensor_sub{this, ORB_ID(sensor_test_data)};
};
2. SubscriptionCallbackWorkItem의 소름 돋는 은닉성(Encapsulation)의 마법
위 코드의 private 멤버 변수 선언부(_sensor_sub) 한 줄의 우아함을 주목하라. 우리가 과거 19.5.1 단원에서 무려 수십 줄에 걸쳐 피눈물 흘리며 짰던 파이프 다이렉트 개통(orb_subscribe), 명세서 배열 세팅(px4_pollfd_struct_t), 무한 루프, 그리고 타임아웃 튜닝 메커니즘의 모든 하드웨어적 코어 로직이 저 단 한 줄의 C++ 인스턴스 선언 블록체인 안으로 완벽히 통제 및 은닉(Encapsulation)되어 완전히 숨겨져 버렸다.
**uORB::SubscriptionCallbackWorkItem**이라는 이름의 이 PX4 프레임워크의 최고급 하이엔드 래퍼(Wrapper) 클래스는, 힙/스택에 멤버로 생성 배치되는 찰나의 순간, OS 커널 코어와 소켓을 독립적으로 직결 개통시켜 둔다.
그리고 그 등록된 토픽 파이프망(sensor_test_data)을 자기가 알아서 백그라운드 인터럽트로 무미건조하게 노려보다가, 퍼블리셔의 실제 페이로드 데이터가 인입되는 바로 그 절정의 타격 순간에, **this(즉, 나 자신 SensorSubscriber 객체의 메모리 포인터 주소)**를 자신이 물고 결속되어 있는 최상위 워크 큐 생태계 백그라운드에 강제로 탑승시켜, 내장된 Run() 전용 메서드의 실행 틱(Tick)을 스케줄링(Schedule) 예약 대기열에 박아 넣어버린다.
이 놀라운 아키텍처를 얻은 이제 모듈 해커 개발자는 그 지긋지긋하고 귀찮았던 while 무한 루프 스케줄링 감방과 블로킹 usleep 포인터 감옥을 완벽히 탈출하여, 오직 링 버퍼에 데이터가 실제로 100% 유효할 때만 극도로 우아하게 소환당하는 오버라이딩 Run() 메서드 하단 속, 기체의 치명적 비즈니스 실제 코딩 로직(자세 행렬식, 매트릭스 필터 제어기 등) 코드 타설에만 100% 온전히 물리 집중할 수 있는 완벽한 면죄부를 얻게 된 것이다.