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
- Không dùng biến toàn cục/static (hoặc chỉ đọc, không ghi)
- Không sửa đổi code của chính mình (self-modifying code)
- Không gọi hàm non-reentrant (malloc, printf, strtok, localtime...)
- Chỉ dùng biến cục bộ (stack) và tham số
- 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àm | Lý do | Thay thế reentrant |
strtok | Static buffer nội bộ | strtok_r (POSIX), std::stringstream |
localtime/gmtime | Static struct tm | localtime_r, std::chrono |
rand | Static state | rand_r, <random> |
malloc/free | Heap toàn cục | Thread-local allocator, pool |
printf/scanf | Lock nội bộ, buffer | Khó thay thế hoàn toàn |
getenv | Static buffer | getenv_s (C11), secure_getenv |
Reentrant vs Thread-safe
| Khái niệm | Ý nghĩa |
| Reentrant | An toàn khi bị ngắt và gọi lại trong cùng thread (ISR, signal) |
| Thread-safe | An 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