我的 Qt 应用程序中有 RAM 存储库:
struct mutexData{
pthread_mutex_t* mutex;
pthread_cond_t* condition;
};
/**
* in memory database implementation shared pointers to records are kept on the
* free store as this is the way std::vector allocates its elements
* records itself are also on heap because this is the way we allocate them
* in PosixClient callbacks
*/
class Repository {
public:
typedef boost::shared_ptr<pthread_mutex_t> mutex_ptr;
typedef boost::shared_ptr<pthread_cond_t> cond_ptr;
typedef std::map<const IBAdditions::ContractEvent,
std::vector<IBAdditions::rec_ptr> > ContractEventDataMap;
typedef std::map<const IBAdditions::ContractEvent, mutexData>
ContractEventMutexMap;
Repository(const std::vector<IBAdditions::ContractEvent>& contractEventVector);
Repository();
virtual ~Repository();
/**
* insert record into repository
* @param ce key to the map, IB::Contract and IBAdditions::Event
* @param rptr record to be stored into repository
*/
void putRecord(const IBAdditions::ContractEvent ce,
const IBAdditions::rec_ptr rptr);
/**
* get a reference to corresponding vector based on ContactEvent key
* @param contractEvent
* @return reference to vector of records
*/
std::vector<IBAdditions::rec_ptr>& operator[](const
IBAdditions::ContractEvent& contractEvent){
return contractEventDataMap_[contractEvent];
}
private:
Repository(const Repository& orig);
ContractEventDataMap contractEventDataMap_;
ContractEventMutexMap contractEventMutexMap_;
};
现在,我有一个主线程,它会不断地将记录放入 ContractEvents(键)的存储库向量中。当出现给定 ContractEvent 的新记录时,我希望特定的 GUI 对象根据存储库向量中的数据进行计算。所以这样的对象需要访问多个 repo 条目。我考虑这样的设计,对象有 posix 线程等待条件变量,然后每个传入的记录将被放入 repo,Repository::putRecord
函数将唤醒等待此条件变量(在此向量上)的睡眠线程。这是一个好的设计吗?其次,应该如何添加互斥锁?在完整 Repo 上的每个向量或一个互斥锁上?我是否需要在完整地图或每个条目上保护访问?一个线程可以同时使用vector1、vector2数据,其他线程同时使用vector3和vector4数据吗?或者这是一个并发访问(实际上是同一张地图)?
我希望每个对象在它感兴趣的向量中有新记录时开始自己的计算。例如,我将有 8 个对象,每个对象都需要访问 2 个或更多向量,有些可能会重叠,所以我认为每个向量都必须受到保护。我希望每个对象都独立完成以实现并行性。如果两个对象试图访问同一个向量怎么办?
目前我在想这样的事情:
/**
*
* @param ce key to the map, IB::Contract and IBAdditions::Event
* @param rptr record to be stored into repository
* TODO: lock mutex here before push_back into Repository
* and wake up waiting threads
*/
void Repository::putRecord(const IBAdditions::ContractEvent ce,
const IBAdditions::rec_ptr rptr) {
if(contractEventDataMap_.find(ce) == contractEventDataMap_.end()){
/*
* there is no such ContractEvent in the map
* next available mutex's identifier is contractEventDataMap_.size()
* ( before inserting ce into contractEventDataMap_ )
*/
printf("[Repository:putRecord] locking mutex %d\n",
contractEventDataMap_.size());
mutexData m;
m.mutex = &repoMutexes[contractEventDataMap_.size()];
m.condition = &repoConditions[contractEventDataMap_.size()];
contractEventMutexMap_[ce] = m;
contractEventDataMap_[ce] = std::vector<IBAdditions::rec_ptr>();
}
printf("[Repository] vector size is;%d\n", contractEventDataMap_[ce].size());
contractEventDataMap_[ce].push_back(rptr);
printf("[Repository] vector size is;%d\n", contractEventDataMap_[ce].size());
}