Использовать errno в многопоточном приложении http://www.cplusplus.com/reference/cerrno/errno/ указывает, что это должно быть реализовано локально в каждом потоке. Что это значит?
errno
должно быть thread-local
, В каждом thread
Значение этой переменной может быть разным.
что это должно быть локально реализовано в каждом потоке
Это не ваша обязанность осуществлять errno
как thread_local
переменная. Это работа для разработчиков компиляторов.
errno — макрос препроцессора, используемый для индикации ошибок.
Он расширяется до локально модифицируемого потока lvalue типа int. (начиная с C ++ 11)
Просто в компиляторах C ++ 11 этот код никогда не должен утверждать
#include <iostream>
#include <cerrno>
#include <thread>
#include <cassert>
int g_errno = 0;
void thread_function()
{
errno = E2BIG;
g_errno = errno;
}
int main()
{
errno = EINVAL;
std::thread thread(thread_function);
thread.join();
assert(errno != g_errno && "not multithreaded");
}
Исторически, errno
был общий переменная типа int
— т. е. каждый модуль принес свое собственное определение, и компоновщик отвечал за их объединение. Так что программы просто заявлены int errno;
глобально и имел рабочее определение.
Это ломается в многопоточных средах, потому что есть только одна переменная. Таким образом, errno.h
Теперь необходимо определить что-то, что является именующий int
и программы не должны определять свои errno
,
Библиотека GNU C, например, определяет что-то похожее на
#define errno (*(__errno_location()))
где __errno_location()
это встроенная функция, которая вычисляет адрес локального потока errno
,
Все это не имеет отношения к приложению, за исключением того, что это ошибка, чтобы определить свой собственный errno
,
Это означает, что каждый поток должен иметь свой собственный экземпляр errno
переменная
Реализация может легко достичь этого, используя что-то вроде:
int __thread errno;
__thread
является расширением gcc, которое гарантирует, что переменная является локальной для потока (поэтому один поток не может перезаписать другой экземпляр переменной для другого потока)
Как пользователь errno, вам не нужно беспокоиться об этом. Вам даже не нужно беспокоиться о том, что errno, возможно, был предварительно изменен другим потоком.