在我的程序中,我有全局数据。
每个程序模块必须具有对数据的读写访问权限。到目前为止,我不使用线程,而是Qt的信号和插槽,因此--尽管我还没有遇到崩溃--我想我需要在某个时候同步。
因此,每个模块保存的数据如下:
const std::vector<T>& data;其中T是一个自定义类。因此,每个模块都可以读取数据。为了保持一致性,vector本身禁止并发删除或删除。这些都是使用可以同步的全局函数(如addToData(T elem)、removeFromData(int id))来完成的。请注意,向量本身通过引用声明为共享,因此上述全局函数中的一个更改将导致每个程序模块中的数据一致。
==>,这意味着可以以一种安全的方式从任何地方读取和添加/删除数据。
我遇到的问题是数据的修改。T的策划者们知道种族状况。使用data,我希望允许像data.at(3).setAttr("hello")这样的调用,但是对于常量向量,at()只返回常量引用。我怎么才能让它起作用?我可以抛开不变,但这感觉不对。
考虑到我的架构,我也愿意听取一些建议。
发布于 2014-10-03 11:00:20
这种情况正是您想要抛弃恒常的地方。您已经仔细地设计了您的系统以正确地工作,所以当您已经完全准备好了它并且它是正确的事情时,不要对抛弃const感到难过。
发布于 2014-10-03 11:05:16
下面是工作低开销的解决方案(虽然没有很好的封装)。一个@JonathanWakely的评论很好地总结了这个想法:“添加一个带函子的全局函数,并将它应用到非const向量中。”
header.h
struct no_synchronization {
struct mutex {}
struct guard {
guard(mutex&) {}
};
};
struct serialized {
typedef std::mutex mutex;
typedef std::lock_guard<mutex> guard;
};
template <class T, class S = no_synchronization>
class spaghetti {
typedef typename S::mutex mutex;
typedef typename S::guard guard;
static mutex mutex_;
static std::vector<T> vector_;
template <class F>
static void read_global_vec(F const& f) {
guard lock(mutex_);
std::vector<T> const& ref = vector_;
f(ref);
}
template <class F>
static void write_global_vec(F const& f) {
guard lock(mutex_);
f(vector_);
}
}如果向量的内容很少发生变化,那么可以使用shared_ptr进行复制,以将争用降到最低。
发布于 2014-10-03 11:17:30
既然你问我建议
vector。这也将消除您提到的全局函数,这是很好的。如果您希望类的实例是const,那么在内部使用mutable向量。const_cast,但是尝试将其隐藏在函数中的某个地方。为了详细说明(1),因为我在评论中被要求:
您需要向量的功能,这是一个很好的匹配您的需要。但是矢量的接口对于你所需要的东西是笨拙的。这是一种经常遇到的情况,包装器是默认的解决方案。包装器是一个新的类,它的接口与您的需要相匹配,但是它的实现实际上只是将所有的工作委托给另一个类。使用包装器的目的是使包装器对象更容易正确使用,更难使用错误。它可能看起来有点像这样(没有测试,不会编译):
class AWrapperForDemonstration
{
public:
MyCustomClass& GetByIndex(int i) const // can throw
{
std::lock_guard<std::mutex> lock(_mutex);
return _storage[i];
}
size_t Size(int i) const
{
std::lock_guard<std::mutex> lock(_mutex);
return _storage.size();
}
void Add(MyCustomClass& addThis)
{
std::lock_guard<std::mutex> lock(_mutex);
_storage.push_back(addThis);
}
bool Remove(MyCustomClass& removeThis)
{
std::lock_guard<std::mutex> lock(_mutex);
auto it =_storage.find(removeThis);
if (it == _storage.end())
return false;
_storage.erase(it);
}
template <F> void ForEach(F const& f) const
{
std::lock_guard<std::mutex> lock(_mutex);
for (auto& i : _storage)
f(i);
}
private:
std::vector<MyCustomClass> _storage;
std::mutex _mutex;
}https://stackoverflow.com/questions/26177709
复制相似问题