我的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(key)的存储库向量中。当出现给定ContractEvent的新记录时,我希望特定的GUI对象基于来自存储库向量的数据来计算某些内容。因此,此类对象需要访问多个repo条目。我想到这样的设计,对象有posix线程等待条件变量,当每个传入的记录然后被放入repo时,Repository::putRecord
函数将唤醒等待这个条件变量的休眠线程(在这个向量上)。这是一个很好的设计吗?其次,如何添加互斥量?在完整回购的每个载体或一个互斥体上?我是否需要在完整地图或每个条目上保护访问权限?一个线程可以同时使用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());
}