Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Hàm tái nhập (Reentrant Function) trong C/C++

Hàm tái nhập (Reentrant Function) là hàm có thể bị ngắt giữa chừng (bởi ngắt, signal, thread khác), chạy xong đoạn ngắt, rồi tiếp tục an toàn mà không gây lỗi logic.

Điều kiện cần để reentrant

  1. Không dùng biến toàn cục/static (hoặc chỉ đọc, không ghi)
  2. Không sửa đổi code của chính mình (self-modifying code)
  3. Không gọi hàm non-reentrant (malloc, printf, strtok, localtime...)
  4. Chỉ dùng biến cục bộ (stack) và tham số
  5. Không truy cập tài nguyên chia sẻ không được bảo vệ

Ví dụ: NON-reentrant


int global_x = 10;

int my_function() {
    return global_x * 10;  // Dùng global -> NON-reentrant
}

int my_second_function() {
    return my_function() * 20;  // Gọi non-reentrant -> NON-reentrant
}

Ví dụ: REENTRANT


// Chỉ dùng tham số và biến cục bộ
int my_function(int x) {
    return x * 10;
}

int my_second_function(int x) {
    return my_function(x) * 20;
}

// Hoặc dùng thread-local storage (C++11)
thread_local int tls_counter = 0;

int reentrant_counter() {
    return ++tls_counter;  // Mỗi thread có counter riêng
}

Các hàm thư viện thường NON-reentrant

HàmLý doThay thế reentrant
strtokStatic buffer nội bộstrtok_r (POSIX), std::stringstream
localtime/gmtimeStatic struct tmlocaltime_r, std::chrono
randStatic staterand_r, <random>
malloc/freeHeap toàn cụcThread-local allocator, pool
printf/scanfLock nội bộ, bufferKhó thay thế hoàn toàn
getenvStatic buffergetenv_s (C11), secure_getenv

Reentrant vs Thread-safe

Khái niệmÝ nghĩa
ReentrantAn toàn khi bị ngắt và gọi lại trong cùng thread (ISR, signal)
Thread-safeAn toàn khi gọi đồng thời từ nhiều thread
Mối quan hệReentrant ⇒ Thread-safe (nếu không dùng TLS). Thread-safe ⇏ Reentrant

Ứng dụng thực tế

  • ISR (Interrupt Service Routine): Chỉ gọi hàm reentrant
  • Signal handler: Chỉ gọi async-signal-safe functions (POSIX list)
  • Recursive functions: Tự gọi chính nó → cần reentrant
  • Embedded/Rtos: Shared library code giữa tasks

C++11+: Thread-local thay thế static


// Non-reentrant do static
int counter() {
    static int count = 0;
    return ++count;
}

// Reentrant với thread_local
int counter() {
    thread_local int count = 0;
    return ++count;
}

Tóm tắt

  • Reentrant = An toàn khi bị ngắt & gọi lồng (recursion, ISR, signal)
  • Không global/static mutable, không gọi non-reentrant
  • Thread-safe ≠ Reentrant
  • C++11: thread_local, <random>, <chrono> giúp viết reentrant dễ hơn