Действительно ли fprintf ориентирован на многопотоковое исполнение на OS X?

Действительно ли fprintf ориентирован на многопотоковое исполнение на OS X? Если так, где это документируется?

7
задан dsolimano 9 May 2012 в 05:01
поделиться

2 ответа

Это был хороший вопрос, хотя подобные вопросы здесь задавались много раз. Меня интересовал аспект OSX, потому что я сам пытался освоить эту систему. (возможно, вам следует добавить тег OSX)

Я ДУМАЮ fprintf () является потокобезопасным в OSX. Моя первая причина для этого заключается в том, что люди Дарвина шли в этом направлении, о чем свидетельствует их выбор отказаться от старого глобального «errno» в пользу функции errno (). Для документации просто следуйте '/usr/include/errno.h'. Без этого ни один из компонентов libc не был бы потокобезопасным. Однако использование функции errno () ничего не доказывает о fprintf (). Это только начало. Я уверен, что всем известна по крайней мере одна ситуация, когда Apple не реализовала хорошую идею.

Еще одна причина, по которой я верю в «потокобезопасность» fprintf (), - это исходный код , который должен быть «настоящим», по крайней мере до 10.6, когда Apple закрыла (part / все) OSX. Просканируйте этот код для поиска «MT-Safe», и вы увидите ЗАЯВЛЕНИЕ о том, что версия 'vfprintf ()' без локализации является потокобезопасной. Опять же, это ничего не доказывает. Тем не менее, это форма документации, которую вы хотели.

Моя последняя причина полагать, что fprintf () является поточно-ориентированной, была тестовым примером. Это тоже ничего не доказывает. Возможно, это доказывает, что буферное пространство является потокобезопасным. Хорошо, это был повод написать небольшую программу для развлечения. Собственно, я этого не писал. Я нашел в сети скелет и изменил его. Определение «FLUSH_BUFFER» позволяет более четко видеть, что происходит. Если этот макрос не определен, вы получите тест буфера сортировки (тот же текст без некоторых символов конца строки). Я не мог придумать, как устроить более значимое столкновение потоков.

Я предполагаю, что вы можете записывать в несколько файлов. Запись в один файл, вероятно, лучший тест. Прилагаемая программа не является окончательным тестом. Хотя ее можно было бы расширить, я не уверен, что какая-то программа действительно может быть окончательной. Итог: возможно, вам стоит просто MUTEX ваши вызовы 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);
}
3
ответ дан 7 December 2019 в 05:22
поделиться

Спецификация потоков POSIX (AKA Pthreads), которой соответствует OS X, требует, чтобы функции stdio были потокобезопасными. Он также предоставляет функции flockfile и funlockfile , чтобы гарантировать, что другие потоки не могут чередовать ввод-вывод в ФАЙЛ *, пока он заблокирован.

См. http://pubs.opengroup.org/onlinepubs/007908799/xsh/threads.html , в частности, в разделе под названием « Безопасность потоков ».

5
ответ дан 7 December 2019 в 05:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: