Являются подставляемые функции в C/C++ способом сделать их ориентированными на многопотоковое исполнение?

В этом сценарии вы можете просто использовать ts.createIdentifier. Нет выражения доступа к свойству в foo().

const statement = ts.createExpressionStatement(
    ts.createCall(ts.createIdentifier("foo"), undefined, undefined)
);

Кстати, проверьте мой сайт ts-ast-viewer . Теперь он покажет код API компилятора, который создаст код в редакторе.

6
задан alvatar 13 April 2009 в 11:53
поделиться

10 ответов

Когда вы объявляете функцию как встроенную, это просто подсказка компилятору. Статические переменные имеют четкое определение в языке. Если компилятор действительно встроил функцию, он по-прежнему обязан сохранять статические переменные общими для всех экземпляров функции. Следовательно, они останутся глобальными и должны быть защищены в среде MT.

Что касается локальных переменных, если они не используются вне функции, они являются потокобезопасными независимо от того, включена ли функция или нет.

25
ответ дан 8 December 2019 в 02:00
поделиться

Нет, вы не правы. Для статической переменной, независимо от того, встроена она или нет, существует только один экземпляр. Встроенные функции не влияют на безопасность потоков, так или иначе.

29
ответ дан 8 December 2019 в 02:00
поделиться

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

2
ответ дан 8 December 2019 в 02:00
поделиться

На вашем месте я бы не использовал статические переменные внутри встроенных функций. Более старые версии стандарта C ++ требовали иного значения, чем текущее.

ПРИМЕЧАНИЕ. Исторический ответ. Не полезно сегодня.

2
ответ дан 8 December 2019 в 02:00
поделиться

встраивание не влияет на то, является ли функция поточно-ориентированной. Например:

inline void doTheThing()
{
   int a = 42; // this is thread safe, but it would be anyway
   vector<int> * answers = getTheAnswers(); // this is not thread safe
}

Доступ к вектору, на который указывает getTheAnswers (), не является потокобезопасным, поскольку нет кода, препятствующего выполнению кода любым другим потоком. Включение функции в линию не препятствует вызову doTheThing () несколькими потоками одновременно. Чтобы сделать поток doTheThing () безопасным, вам необходимо убедиться, что он не вызывается параллельно или все общие (нелокальные) данные, к которым вы обращаетесь, защищены.

1
ответ дан 8 December 2019 в 02:00
поделиться

Каждый поток получает свою собственную копию локальных объектов, поэтому с ними не может быть проблем, связанных с потоками, независимо от того, выполняете ли вы он встроен или нет.

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

6
ответ дан 8 December 2019 в 02:00
поделиться

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

При использовании стандартного компилятора вы гарантированно получите один экземпляр каждой статической переменной независимо от встраивания и должны позаботиться о безопасности потоков самостоятельно.

2
ответ дан 8 December 2019 в 02:00
поделиться

Совсем нет.

Чтобы быть поточно-ориентированным, функция должна быть поточно-ориентированной с уважение к ЛЮБОМУ экземпляру функции, включая себя; несколько потоков могут выполнять один и тот же экземпляр встроенной функции в одно и то же время.

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

0
ответ дан 8 December 2019 в 02:00
поделиться

Все статические переменные в (обычных и встроенных) функциях попадают в кучу. Куча НЕ БЕЗОПАСНАЯ .

-3
ответ дан 8 December 2019 в 02:00
поделиться

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

Рассмотрим следующие функции:

int factorial(const int n)
{
  if (n <= 1)
  {
    return 1;
  }

  return factorial(n - 1);
}

Эта функция не может быть встроена, поскольку она рекурсивна, но при этом совершенно потокобезопасна.

int factorial_2(int n)
{
  int Result = 1;

  while (n > 1)
  {
    Result *= n--;
  }

  return Result;
}

Эта функция может быть встроена компилятором, и при этом она остается полностью потокобезопасной.

int RefCount;

void DecRef()
{
  --RefCount;
}

Эта функция не является потокобезопасной, независимо от того, встроил ее компилятор или нет.

3
ответ дан 8 December 2019 в 02:00
поделиться