Inline заставляет функцию работать как макрос. Inline никак не связан с атомарным.
AFAIK inline - это подсказка, и gcc может ее игнорировать. При встраивании код из встроенного функционала, называемого его B, копируется в функцию вызывающего абонента, A. Не будет вызова от A к B. Это, вероятно, сделает ваш исполняемый файл быстрее за счет увеличения размера. Наверное? Exe может стать меньше, если ваша встроенная функция мала. Исполняемый файл может стать медленнее, если встраивание затруднит оптимизацию функции A. Если вы не укажете inline, во многих случаях gcc примет для вас встроенное решение. Функции-члены классов являются встроенными по умолчанию. Вы должны явно указать gcc не делать автоматических строк. Кроме того, gcc не будет встроен, когда оптимизации отключены.
Линкер не будет встроенным. Таким образом, если модуль A extern ссылался на функцию, помеченную как встроенную, но код находился в модуле B, модуль A будет вызывать функцию, а не вставлять ее. Вы должны определить функцию в заголовочном файле и объявить ее как extern inline func foo (a, b, c). На самом деле все намного сложнее.
inline void test(void); // __attribute__((always_inline));
inline void test(void)
{
int x = 10;
long y = 10;
long long z = 10;
y++;
z = z + 10;
}
int main(int argc, char** argv)
{
test();
return (0);
}
Не в строке:
!{
main+0: lea 0x4(%esp),%ecx
main+4: and $0xfffffff0,%esp
main+7: pushl -0x4(%ecx)
main+10: push %ebp
main+11: mov %esp,%ebp
main+13: push %ecx
main+14: sub $0x4,%esp
! test();
main+17: call 0x8048354 <test> <--- making a call to test.
! return (0);
main()
main+22: mov $0x0,%eax
!}
main+27: add $0x4,%esp
main+30: pop %ecx
main+31: pop %ebp
main+32: lea -0x4(%ecx),%esp
main+35: ret
Инлайн:
inline void test(void)__attribute__((always_inline));
! int x = 10;
main+17: movl $0xa,-0x18(%ebp) <-- hey this is test code....in main()!
! long y = 10;
main+24: movl $0xa,-0x14(%ebp)
! long long z = 10;
main+31: movl $0xa,-0x10(%ebp)
main+38: movl $0x0,-0xc(%ebp)
! y++;
main+45: addl $0x1,-0x14(%ebp)
! z = z + 10;
main+49: addl $0xa,-0x10(%ebp)
main+53: adcl $0x0,-0xc(%ebp)
!}
!int main(int argc, char** argv)
!{
main+0: lea 0x4(%esp),%ecx
main+4: and $0xfffffff0,%esp
main+7: pushl -0x4(%ecx)
main+10: push %ebp
main+11: mov %esp,%ebp
main+13: push %ecx
main+14: sub $0x14,%esp
! test(); <-- no jump here
! return (0);
main()
main+57: mov $0x0,%eax
!}
main+62: add $0x14,%esp
main+65: pop %ecx
main+66: pop %ebp
main+67: lea -0x4(%ecx),%esp
main+70: ret
Вы можете быть уверены, что только атомарные функции - это gcc атомарные встроенные . Вероятно, простые инструкции по сборке одного кода операции также являются атомарными, но они не могут быть такими. По моему опыту, установка 6x86 или чтение 32-битного целого числа являются атомарными. Вы можете догадаться, может ли строка кода c быть атомарной, посмотрев на сгенерированный код сборки.
Приведенный выше код был скомпилирован в 32-битном режиме. Вы можете видеть, что long long требует 2 кода операции для загрузки. Я предполагаю, что это не атомно. Интенты и длинные принимают один код операции для установки. Вероятно, атомный. y ++ реализован с помощью addl, который, вероятно, является атомарным. Я продолжаю говорить, вероятно, потому что микрокод на процессоре может использовать более одной инструкции для реализации операции, и знание этого выше моего уровня оплаты. Я предполагаю, что все 32-битные записи и чтения являются атомарными. Я предполагаю, что приращения нет, потому что они обычно выполняются с чтением и записью.
Но проверьте это, когда скомпилировано в 64-битном
! int x = 10;
main+11: movl $0xa,-0x14(%rbp)
! long y = 10;
main+18: movq $0xa,-0x10(%rbp)
! long long z = 10;
main+26: movq $0xa,-0x8(%rbp)
! y++;
main+34: addq $0x1,-0x10(%rbp)
! z = z + 10;
main+39: addq $0xa,-0x8(%rbp)
!}
!int main(int argc, char** argv)
!{
main+0: push %rbp
main+1: mov %rsp,%rbp
main+4: mov %edi,-0x24(%rbp)
main+7: mov %rsi,-0x30(%rbp)
! test();
! return (0);
main()
main+44: mov $0x0,%eax
!}
main+49: leaveq
main+50: retq
Я предполагаю, что addq может быть атомарным.