[libuv] uv_loop_t, uv_handle_t 정리

lsh235·2024년 11월 16일
0

libuv

목록 보기
5/5

1. 기본 개념

uv_loop_t
역할: 이벤트 루프를 관리합니다. 모든 비동기 작업은 이벤트 루프를 통해 처리됩니다.
설명: 프로그램의 메인 루프로 생각할 수 있으며, 다양한 이벤트(타이머, I/O 등)를 감시하고 처리합니다.
uv_handle_t
역할: 다양한 I/O 작업을 추상화한 핸들입니다.
설명: uv_handle_t는 추상 타입으로, 실제로는 uv_timer_t, uv_tcp_t 등 다양한 구체적인 핸들을 사용합니다.


2. code

CustomHandle.h

#ifndef CUSTOM_HANDLE_HPP
#define CUSTOM_HANDLE_HPP

#include <uv.h>
#include <iostream>

class CustomHandle {
public:
    CustomHandle(uv_loop_t* loop, int data);
    ~CustomHandle();

    // 초기화 함수
    bool init();

    // 시작 함수 (이벤트 발생)
    bool start();

    // 핸들 닫기
    void close();

private:
    uv_loop_t* loop_;
    int some_data_;
    uv_async_t async_;  // uv_async_t를 사용

    // 콜백 함수
    static void on_close(uv_handle_t* handle);
    static void on_event(uv_async_t* async);
};

#endif // CUSTOM_HANDLE_HPP

CustomHandle.cpp

#include "CustomHandle.h"

// 생성자
CustomHandle::CustomHandle(uv_loop_t* loop, int data)
    : loop_(loop), some_data_(data) {
    // uv_async_t의 data 필드에 this 포인터를 저장하여 콜백에서 접근 가능하도록 설정
    async_.data = this;
}

// 소멸자
CustomHandle::~CustomHandle() {
    // 리소스 해제는 close()에서 수행
}

// 핸들 초기화
bool CustomHandle::init() {
    // uv_async_t 초기화
    int r = uv_async_init(loop_, &async_, CustomHandle::on_event);
    if (r < 0) {
        std::cerr << "uv_async_init 실패: " << uv_strerror(r) << std::endl;
        return false;
    }
    return true;
}

// 이벤트 콜백 함수
void CustomHandle::on_event(uv_async_t* async) {
    CustomHandle* self = static_cast<CustomHandle*>(async->data);
    std::cout << "커스텀 이벤트 발생! 데이터: " << self->some_data_ << std::endl;

    // 이벤트 처리 후 핸들을 닫음
    self->close();
}

// 핸들 종료 콜백
void CustomHandle::on_close(uv_handle_t* handle) {
    std::cout << "커스텀 핸들이 종료되었습니다." << std::endl;
    CustomHandle* self = static_cast<CustomHandle*>(handle->data);
    delete self;
}

// 핸들 시작 (이벤트 발생)
bool CustomHandle::start() {
    // 비동기 이벤트 전송
    int r = uv_async_send(&async_);
    if (r < 0) {
        std::cerr << "uv_async_send 실패: " << uv_strerror(r) << std::endl;
        return false;
    }
    return true;
}

// 핸들 닫기
void CustomHandle::close() {
    if (!uv_is_closing(reinterpret_cast<uv_handle_t*>(&async_))) {
        uv_close(reinterpret_cast<uv_handle_t*>(&async_), CustomHandle::on_close);
    }
}

main.cpp

#include "CustomHandle.h"

int main() {
    // 이벤트 루프 초기화
    uv_loop_t* loop = uv_default_loop();

    // 커스텀 핸들 생성
    CustomHandle* custom_handle = new CustomHandle(loop, 42);

    // 핸들 초기화
    if (!custom_handle->init()) {
        delete custom_handle;
        return 1;
    }

    // 핸들 시작 (이벤트 발생)
    if (!custom_handle->start()) {
        delete custom_handle;
        return 1;
    }

    // 이벤트 루프 실행
    uv_run(loop, UV_RUN_DEFAULT);

    // 루프 정리
    uv_loop_close(loop);
    return 0;
}

3. 결과

커스텀 이벤트 발생! 데이터: 42
커스텀 핸들이 종료되었습니다.

4. 상세 설명

CustomHandle.h

멤버 변수:
uvloop_t* loop: 이벤트 루프 포인터.
int somedata: 추가 데이터 (예: 42).
uvasync_t handle: libuv의 기본 핸들 구조체.

멤버 함수:
init(): 핸들을 초기화합니다.
start(): 핸들을 시작하고 이벤트를 발생시킵니다.
close(): 핸들을 닫습니다.
on_event(): 이벤트가 발생했을 때 호출되는 정적 콜백 함수.
on_close(): 핸들이 완전히 닫혔을 때 호출되는 정적 콜백 함수.

CustomHandle.cpp

생성자 및 소멸자:
생성자에서는 이벤트 루프와 추가 데이터를 초기화하고, handle_.data에 this 포인터를 저장하여 콜백 함수에서 객체에 접근할 수 있도록 합니다.
소멸자에서는 리소스 해제를 수행합니다.

init() 함수:
uv_async_init을 호출하여 핸들을 초기화합니다. 여기서는 기본 핸들 타입을 사용하지만, 실제로는 적절한 핸들 타입을 선택해야 합니다.

start() 함수:
uv_async_send를 호출하여 이벤트를 비동기적으로 발생시킵니다.

onevent() 함수:
이벤트가 발생했을 때 호출됩니다. 여기서는 some_data
값을 출력하고 핸들을 닫습니다.

on_close() 함수:
핸들이 완전히 닫혔을 때 호출됩니다. 객체의 메모리를 해제합니다.

close() 함수:
핸들을 닫습니다. 핸들이 이미 닫히지 않은 경우에만 uv_close를 호출합니다.

main.cpp

이벤트 루프 초기화:
uv_default_loop()를 사용하여 기본 이벤트 루프를 가져옵니다.

커스텀 핸들 생성 및 초기화:
CustomHandle 객체를 동적으로 생성하고, init() 함수를 호출하여 핸들을 초기화합니다.

커스텀 핸들 시작:
start() 함수를 호출하여 이벤트를 발생시킵니다.

이벤트 루프 실행:
uv_run(loop, UV_RUN_DEFAULT)을 호출하여 이벤트 루프를 실행합니다. 이때 이벤트가 발생하면 콜백 함수가 호출됩니다.

루프 정리:
uv_loop_close(loop)을 호출하여 이벤트 루프를 정리합니다.

0개의 댓글