Является ли поток fprintf безопасным в OS X?
является ли поток fprintf безопасным на OS X? Если да, то где это документально?
2 ответов
Это был хороший вопрос, хотя подобные вопросы уже задавались здесь много раз. Меня интересовал аспект OSX, потому что я сам пытался ускорить эту систему. (возможно, вам следует добавить тег OSX)
Я думаю fprintf() является потокобезопасным на OSX. Моя первая причина этого заключается в том, что люди Дарвина шли в этом направлении, о чем свидетельствует их выбор отказаться от старой школы глобального "errno" в пользу функции errno(). Для документация, просто следуйте ' / usr / include / errno.h'. Без этого ни один из материалов libc не будет потокобезопасным. Однако использование функции errno () ничего не доказывает в отношении fprintf (). Это только начало. Я уверен, что все знают по крайней мере одну ситуацию, когда Apple не выполнила хорошую идею.
еще одна причина, по которой я верю в "потокобезопасность" fprintf (), - это исходный код, который должен быть "реальной вещью", по крайней мере до 10.6, когда Apple закрыла (часть / все) OSX. Сканируйте этот код для "Mt-Safe" и вы увидите претензии что версия 'vfprintf ()' не является потокобезопасной. Опять же, это ничего не доказывает. Но это форма документации, которую вы хотели.
моей последней причиной полагать, что fprintf() является потокобезопасным, был тестовый случай. Это тоже ничего не доказывает. Возможно, это доказывает, что буферное пространство является потокобезопасным. Ладно, это был предлог, чтобы немного написать. программа для развлечения. Вообще-то, я его не писал. Я нашел скелет в интернете и модифицировал его. Определение "FLUSH_BUFFER" позволяет более четко видеть, что происходит. Если этот макрос не определен, вы получаете тест буфера "sort-of" (тот же текст без некоторых линейных Терминаторов). Я не мог придумать способ организовать более значимое столкновение нитей.
Я предполагаю, что вы можете писать в несколько файлов. Запись в один файл, вероятно, лучший тест. Прилагаемый программа не является окончательным тестом. Хотя он может быть расширен, я не уверен, что какая-либо программа действительно может быть окончательной. Итог: может быть, вы должны просто мьютекс ваши призывы к fprintf().
// artificial test for thread safety of fprintf()
// define FLUSH_BUFFER to get a good picture of what's happening, un-def for a buffer test
// the 'pretty print' (FLUSH_BUFFER) output relies on a mono-spaced font
// a writeable file name on the command line will send output to that file
//
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define FLUSH_BUFFER
#define NTHREAD 5
#define ITERATIONS 3
const char DOTS[] = ". . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
FILE *outFile;
void *PrintHello(void *threadid) {
long tid;
tid = (long)threadid;
for (int i=1; i<=ITERATIONS; i++) {
long delay = (NTHREAD-tid) * 100000 + (ITERATIONS-i+1) * 10000;
#ifdef FLUSH_BUFFER
fprintf(outFile, "%*sStart thread %d iteration %d\n", (tid+1)*4, " ", tid, i);
usleep(delay);
fprintf(outFile, "%*sFinish thread %d iteration %d %*.*sw/delay %d\n",
(tid+1)*4, " ", tid, i, (NTHREAD-tid+1)*4, (NTHREAD-tid+1)*4, DOTS, delay);
#else
fprintf(outFile, "Start thread %d iteration %d ", tid, i);
usleep(delay);
fprintf(outFile, "Finish thread %d iteration %d w/delay %d\n", tid, i, delay);
#endif
}
pthread_exit(NULL);
}
int main (int argc, char *argv[]) {
pthread_t threads[NTHREAD];
char errStr[100];
int rc;
long t;
if(argc > 1) {
if(! (outFile = fopen(argv[1], "w"))) {
perror(argv[1]);
exit(1);
}
} else
outFile = stdout;
for(t=0; t<NTHREAD; t++) {
fprintf(outFile, "In main: creating thread %ld\n", t);
if(rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t)) {
sprintf(errStr, "ERROR; pthread_create() returned %d", rc);
perror(errStr);
exit(2);
}
}
pthread_exit(NULL);
}
спецификация потоков POSIX (AKA Pthreads), которой соответствует OS X, требует, чтобы функции stdio были потокобезопасными. Он также предоставляет flockfile
и funlockfile
функции для обеспечения того, чтобы другие потоки не могли чередовать ввод-вывод в файле *, пока он заблокирован.
посмотреть http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html в разделе "потокобезопасность".