Что касается последовательного повторного входа (т. Е. Если foo()
использует va_start
, безопасно ли для foo()
вызывать bar()
, который также использует va_start
), ответ будет хорошим - до тех пор, покакак экземпляр va_list
не то же самое.Стандарт гласит:
Ни макрос va_start, ни макрос va_copy не должны вызываться для повторной инициализации ap без промежуточного вызова макроса va_end для того же ap.
Итак, вывсе в порядке, пока используется другой va_list
(упоминаемый выше как ap
).
Если под повторным входом вы подразумеваете поточно-ориентированный (что, я полагаю, так и есть, поскольку задействованы мьютексы),вам нужно будет посмотреть на реализацию для специфики.Поскольку стандарт C не говорит о многопоточности, эта проблема действительно зависит от реализации.Я мог бы предположить, что может быть трудно сделать va_start
поточно-ориентированным на некоторых странных или небольших архитектурах, но я думаю, что если вы работаете на современной основной платформе, у вас, вероятно, не будет проблем.
На более популярных платформах, пока в макрос va_start
передается другой аргумент va_list
, у вас не должно возникнуть проблем с несколькими потоками, проходящими через один и тот же va_start
.А поскольку аргумент va_list
обычно находится в стеке (и поэтому разные потоки будут иметь разные экземпляры), вы обычно имеете дело с разными экземплярами va_list
.
Я думаю, что в вашем примеремьютексы не нужны для использования varargs.Тем не менее, если write()
, то, безусловно, имеет смысл сериализовать вызов write()
, чтобы у вас не было нескольких потоков write()
, которые портили вывод друг друга.