c++ /Boost:跨多个方法(getter)调用同步对资源的访问
C++/Boost: Synchronize access to a resource across multiple method (getter) calls
我不确定这是一个关于编程技术或设计的问题,但我愿意听取建议。
问题:我想在数据源(传感器)和消费者之间创建一个抽象层。其理念是消费者只"知道"不同传感器类型的接口(抽象基类)。每种传感器类型通常由几个单独的值组成,这些值都有自己的getter方法。
作为一个例子,我将使用一个简化的GPS传感器
class IGpsSensor {
public:
virtual float getLongitude() = 0;
virtual float getLatitude() = 0;
virtual float getElevation() = 0;
// Deviations
virtual float getLongitudeDev() = 0;
virtual float getLatitudeDev() = 0;
virtual float getElevationDev() = 0;
virtual int getNumOfSatellites() = 0;
};
由于对传感器的更新是由不同的线程完成的(细节取决于接口的实现),同步getter和更新方法似乎是确保一致性的合理方法。
到目前为止一切顺利。在大多数情况下,这种级别的同步应该足够了。然而,有时可能需要获取多个值(使用连续的getXXX()调用),并确保其间不发生更新。这是否必要(以及哪些值是重要的)取决于消费者。
坚持这个例子,在很多情况下,只需要知道经度和纬度(但希望两者都与同一个update()相关)。我承认这可以通过将它们分组到一个"Position"类或结构中来实现。但消费者也可能将传感器用于更复杂的算法,也需要偏差。
现在我在想,什么是正确的方法来做到这一点。
我能想到的解决方案:
将所有可能的值分组到一个结构体(或类)中,并添加一个额外的(同步的)getter,一次返回所有值的副本——在可能10个值中只需要2或3个的情况下,对我来说似乎是很多不必要的开销。
添加一个方法返回对数据源中使用的互斥锁的引用,以允许消费者锁定——这感觉不像是"好的设计"。因为getter已经同步了,所以必须使用递归互斥锁。然而,我假设有多个读取器,但只有一个写入器,因此我宁愿在这里使用共享互斥。
谢谢你的帮助。
如何公开"Reader"接口?要获取阅读器对象,您可以这样做:
const IGpsSensorReader& gps_reader = gps_sensor.getReader();
IGpsSensorReader类可以访问IGpsSensor类的受保护成员。在构造时,它将获取锁。一旦被破坏,它就会释放锁。访问器可以这样做:
{ //block that accesses attributes
const IGpsSensorReader& gps_reader = gps_sensor.getReader();
//read whatever values from gps_reader it needs
} //closing the scope will destruct gps_reader, causing an unlock
您还可以向执行更新的线程公开getwwriter方法。在内部,您可以使用boost的shared_mutex来调解读写器之间的访问。
我在一些简单的项目中使用的一种技术是只提供对代理对象的访问。该代理对象在其生命周期内持有锁,并为我的数据提供实际接口。这种访问本身不进行同步,因为它只能通过已经适当锁定的代理来访问。我从未尝试过将其扩展到一个全面的项目,但它似乎对我的目的很有效。
可能的解决方案:从
派生所有的源类class Transaction {
pthread_mutex_t mtx;
// constructor/destructor
public:
void beginTransaction() { pthread_mutex_lock(&mtx); } // ERROR CHECKING MISSING
void endTransaction() { pthread_mutex_unlock(&mtx); } // DO ERROR CHECKING
protected:
// helper method
int getSingle(int *ptr)
{ int v; beginTransaction(); v=*ptr; endTransaction(); return v; }
};
如果需要读取多个值,请使用begin/endTransaction方法。要定义getValue函数,只需调用getSingle,并带指针指向适当的成员[这只是一个方便的方法,这样您就不必在每个getValue函数中调用begin/endTransaction]。
您将需要充实一些细节,因为如果您的getValue函数使用begin/endTransaction,您将无法在事务中调用它们。(互斥锁只能锁定一次,除非它被配置为递归。)
- 什么时候调用组成单元对象的析构函数
- 当对套接字 send() 的同步调用由于连接另一端丢失而被阻止时,如何恢复?
- ofstream::close() 是否在 Linux 上调用同步?
- Vulkan是否需要在多个具有透明度的平局调用之间进行同步
- 关于C++ REST SDK 和同步调用
- 异步操作的 Asio 处理程序在其同步对应项正常工作时不会调用
- 使用 P/调用传递取消标志时是否需要同步
- 从多个线程对共享对象的同步方法调用
- 嵌入在c中的Python.正在调用pyrun_simplestring同步
- 可以使对AudioObjectSetPropertyData的调用同步吗
- 如何从另一个线程的 cpp 代码同步调用 qml 信号处理程序
- C++:如何异步调用同步库调用
- 为什么std::async即使指定了std::launch::async标志,也要同步调用函数?
- 同步来自多个对象的异步调用
- 对运算符的调用是否'delete'同步的?
- 当调用ReadDirectoryChangesW时,只有第一次调用返回任何更改(同步和异步)
- c++ /Boost:跨多个方法(getter)调用同步对资源的访问
- 是boost::信号槽被同步或异步调用
- 使用异步调用与在线程中使用同步调用相同
- 如何使用 MethodInvoker 委托在 cli c++ 中同步对控件线程的调用