Во встроенном программировании необходимо создавать атомарные разделы кода — так называемые критические разделы. Они обычно реализуются с помощью макросов, например, так:
#define ENTER_CRITICAL() int saved_status_ = CPU_STATUS_REGISTER; __disable_irq();
#define EXIT_CRITICAL() CPU_STATUS_REGISTER = saved_status_
То есть при вводе состояния прерывания (включено или отключено) сохраняется; на выходе — восстанавливается. Проблема в том, что для этого нужна дополнительная переменная.
Мой вопрос: возможно ли создавать критические разделы с помощью функций constexpr (и избавиться от макросов, что так всегда)?
RAII решение будет традиционным:
struct CriticalSection {
int saved_status_;
void Enter() {
saved_status_ = CPU_STATUS_REGISTER;
__disable_irq();
}
CriticalSection() { Enter(); }
void Exit() {
CPU_STATUS_REGISTER = saved_status_;
}
~CriticalSection() {
Exit(); // Can you call this more than once safely? Dunno.
}
};
вы бы использовали это так:
void foo() {
// unprotected code goes here
{
CriticalSection _;
// protected code goes here
}
// unprotected code goes here
}
Делать это без какого-либо состояния невозможно, потому что CPU_STATUS_REGISTER
это значение времени выполнения. Состояние в C / C ++ в основном хранится в переменных.
Я сильно подозреваю, что на любом нетривиальном уровне оптимизации вышеупомянутый класс RAII будет компилироваться точно в тот же код, к которому скомпилированы ваши макросы, за исключением того, что вам больше не нужно помнить EXIT_CRITICAL ().
Других решений пока нет …