让我们假设它是一些ARM控制器的嵌入式开发。让我们假设我们有一些变量,可以从中断或" mainThread" - (它是"主循环"还是RTOS线程)。在C世界中,在这种情况下应使用volatile
关键字,代码可能如下所示:
/* Some subsystem .C file */
static volatile uint8_t state;
void on_main_thread(void) {
state = 1; /* Changing state in this context */
}
void on_interrupt(void) {
state = 0; /* Changing state from interrupt */
}
uint8_t get_state(void) {
return state; /* Getting the state in whatever context */
}
在这种情况下, volatile
关键字至关重要。现在我们公司将一些代码重写为C ++,同样的子系统示例如下所示(我在这里使用枚举来强调问题)
class SomeSubsystem
{
public:
enum class States
{
Off,
Idle,
Up,
Down,
};
States getState() const { return mState; }
void onMainThread(void) {
mState = States::Idle; // Changing state in this context
}
// Somehow this function is called from the interrupt
void onInterrupt(void) {
mState = States::Up; // Changing state from interrupt
}
private:
States mState; // <-- Here! Volatile?
//...
};
现在States mState
应该是易变的,因为它在不同的上下文之间共享。但是,如果将其设置为不稳定...那么volatile
就像瘟疫一样对C ++类起作用,而且必须挥发一切。比如volatile enum class States
,getState() volatile
等。这对我来说并不好看(我错了吗?)
因此。在C ++中处理这种情况的正确方法是什么?
P.S。我会尝试定义这种情况&#34; as:&#34;可能使用来自不同上下文的类成员,如中断和正常的代码执行&#34;
答案 0 :(得分:1)
如果您只需要在程序中使用SomeSubsystem的单个实例(根据您发布的C代码,我认为这是可行的)。
如果需要多个实例,则可以将mState修改为States数组或某些类似的结构。
class SomeSubsystem
{
public:
enum class States
{
Off,
Idle,
Up,
Down,
};
States getState() const { return mState; }
void onMainThread(void) {
mState = States::Idle; // Changing state in this context
}
// Somehow this function is called from the interrupt
void onInterrupt(void) {
mState = States::Up; // Changing state from interrupt
}
// Make mState public in order to access it from the rest of your code
// Otherwise, keep it private and create static set/get functions
public:
static volatile States mState; // <-- Here! Volatile?
//...
};
然后在某处(例如,在SomeSubsystem.cpp中)定义mState
volatile SomeSubsystem::States SomeSubsystem::mState = SomeSubsystem::States::Off;
现在您可以像这样在代码中的任何位置访问mState
SomeSubsystem::mState = SomeSubsystem::States::Off;
答案 1 :(得分:1)
我相信,如果类对象本身是volatile
,则只需要volatile
限定方法即可。但是,我认为只要设置相关的成员变量volatile
就不会有任何问题。我已经在something similar上成功完成了该操作(即,它已编译/运行),达到您要实现的目标。例如:
class SomeSubsystem
{
public:
...
void onMainThread(void); // no volatile qualification necessary
void onInterrupt(void); // "
private:
States volatile mState; // only make the relevant member variables volatile
}
SomeSubsystem aSubsystem; // don't make the object volatile
...
aSubsystem.onMainThread();
aSubsystem.onInterrupt();