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 オブジェクトに、リポジトリ ベクトルのデータに基づいて何かを計算させたいと考えています。そのため、そのようなオブジェクトは複数のリポジトリエントリへのアクセスを必要とします。オブジェクトが条件変数で待機しているposixスレッドを持ち、各着信レコードがレポに入れられるとき、そのような設計について考えます。Repository::putRecord
関数は、この条件変数 (このベクトル) を待機しているスリープ状態のスレッドを起動します。これは良いデザインですか?次に、ミューテックスをどのように追加する必要がありますか? 各ベクターまたはフル Repo の 1 つのミューテックスで? マップ全体または各エントリでアクセスを保護する必要がありますか? 1 つのスレッドで vector1 と vector2 のデータを使用し、別のスレッドで vector3 と vector4 のデータを同時に使用できますか? それとも、これは同時アクセスですか (実際には同じマップです)?
vector に関心のある新しいレコードがある場合、各オブジェクトが独自の計算を開始するようにします。たとえば、それぞれが 2 つ以上のベクトルへのアクセスを必要とする 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());
}