Хорошая практика для типов в C, которые не нужны в определенных конфигурациях - PullRequest
2 голосов
/ 22 марта 2019

Я пишу слой абстракции для связанных с потоками функций в C-проекте. Не все платформы, для которых может быть построен код, поддерживают многопоточность; альтернативы доступны для этих платформ.

Заголовочный файл определяет макрос препроцессора, если поддерживается многопоточность, поэтому условные выражения препроцессора могут использоваться для включения и отключения блоков кода, которые требуются только при многопоточности (или только без).

Функции - это тонкие обертки вокруг их собственных реализаций, которые могут отличаться от платформы к платформе. Типы сопоставляются с соответствующими нативными типами с помощью

#define mythread pthread_t

и аналогичные.

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

Это также означает, что абстрагированные типы потоков должны сопоставляться с чем-либо, даже если потоки не поддерживаются, поскольку могут существовать локальные переменные этих типов (опять же, чтобы не загромождать код условными выражениями). Пока что я сопоставляю их с void в однопоточных сборках, например:

#ifdef HAVE_POSIX_THREADS
#define mythread pthread_t
#else
#ifdef HAVE_FUNKY_THREADS
#define mythread FThread
#else /* no supported native thread API available, single-threaded build */
#define mythread void
#endif

Это, однако, происходит за счет невозможности использовать объявления вроде:

mythread new_thread;

(который объявил бы переменную void, недопустимую в C). Эту проблему можно обойти, работая только с указателями на эти типы - фактически каждая функция, которая инициализирует любой из этих типов, выделяет память и возвращает указатель на нее.

Вопрос : Мне было интересно, есть ли более элегантный способ для подобных ситуаций.

1 Ответ

1 голос
/ 22 марта 2019

Можно просто сделать

#else
#define mythread int
#endif

И вы, вероятно, можете сделать все свои тонкие функции-оболочки static inline xxx xxx(xxx), хотя в этом нет особой необходимости, потому что почти все современные компиляторы рассматривают inline какнамек.После этого почти каждый современный компилятор встроит ваши функции-оболочки и выяснит, что new_thread в вашем mythread new_thread на самом деле не используется, а затем оптимизирует его.

Примечание: (просто личный комментарий, возможно,не по теме) Не используйте условные макросы без необходимости.Оптимизация компилятора, такая как мертвый код и устранение неиспользуемых переменных - ваш хороший друг.Хотя не в вашем случае, в руководстве по кодированию GNU рекомендуется использовать

if(some_compiler_flag){ //some_compiler_flag is an 0/1 flag
xxx;
}

вместо

#ifdef some_compiler_flag
xxx
#endif

Современные компиляторы будут компилировать с тем же результатом, а предыдущийболее удобочитаемый и более удобный для инструментов статического анализа и автозаполнения, которые облегчают вашу жизнь.

В вашем случае, если возможно реструктурировать ваш код, я бы предпочел использовать все эти типы потоков как непрозрачные указатели .Например,

//In public headers
union ptr_my_thread_;
typedef ptr_my_thread union ptr_my_thread_;
int my_thread_init(ptr_my_thread);
...

И затем иметь дело со специфичным для платформы кодом в файлах реализации

//In config.h, which takes care of platform dependent flags
#define HAVE_POSIX_THREADS 1
#define HAVE_FUNKY_THREADS 0
...

//In your implementation file
#include <config.h>
union ptr_my_thread_{
    pthread_t *posix;
    FThread *funky;
}
int my_thread_init(ptr_my_thread new_thread){
    if(HAVE_POSIX_THREADS){
        xxx;
    }
}

Это обеспечит модульность и разделение зависимого от платформы кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...