My problem is, I have block matrix updated by multiple threads. Multiple threads may be updating disjoint block at a time but in general there may be race conditions. right
Use a single lock. But instead of using it to protect the entire matrix use it to guard a std::set
(or a boost::unordered_set
) which says which blocks are "locked".
Something like this.
class Block;
class Lock_block
{
public:
Lock_block( Block& block ) : m_block(&block)
{
boost::unique_lock<boost::mutex> lock(s_mutex);
while( s_locked.find(m_block) != s_locked.end() )
{
s_cond.wait(lock);
}
bool success = s_locked.insert(m_block).second;
assert(success);
}
~Lock_block()
{
boost::lock_guard<boost::mutex> lock(s_mutex);
std::size_t removed = s_locked.erase(m_block);
assert(removed == 1);
s_cond.notify_all();
}
private:
Block* m_block;
static boost::mutex s_mutex;
static boost::condition s_cond;
static std::set<Block*> s_locked;
};
It might be a several approaches you can use:
Pre-allocate array if CriticalSection/Mutexes (2500 is not so many), and use block index as a lock index to gather block access; before updating blocks lock all of them which you want to change; do update; unlock;
If computation time is significantly longer then Lock/Unlock, then copy content of the block in thread context and keep block unlocked during that time; before updating block lock it again and make sure that it was not updated by another thread (if it's relevant for this); if it was updated by another thread, then repeat operation;
If the size of the block content is small, use atomic data exchange to update block content, no locks required; just not sure if you use data from one blocks to calculate data for another, in that case locking across all updated blocks required;
Is there reading operation on the matrix? If yes use Read/Write locks to improve performance.