views:

373

answers:

3

I have a multithreaded C++ application which holds a complex data structure in memory (cached data).

Everything is great while I just read the data. I can have as many threads as I want access the data.

However the cached structure is not static.

  • If the requested data item is not available it will be read from database and is then inserted into the data tree. This is probably also not problematic and even if I use a mutex while I add the new data item to the tree that will only take few cycles (it's just adding a pointer).
  • There is a Garbage Collection process that's executed every now and then. It removes all old items from the tree. To do so I need to lock the whole thing down to make sure that no other process is currently accessing any data that's going to be removed from memory. I also have to lock the tree while I read from the cache so that I don't remove items while they are processed (kind of "the same thing the other way around").

"Pseudocode":

function getItem(key)
   lockMutex()
   foundItem = walkTreeToFindItem(key)
   copyItem(foundItem, safeCopy)
   unlockMutex()
   return safeCopy
end function

function garbageCollection()
   while item = nextItemInTree
      if (tooOld) then
         lockMutex()
         deleteItem(item)
         unlockMutex()
      end if
   end while
end function

What's bothering me: That this means, that I have to lock the tree while I'm reading, which means that I can't have two reading processes at the same time anymore.

Any suggestions?

Is there some kind of "this is a readonly action that only collides with writes" Mutex?

+9  A: 

Look into read-write-lock.

You didn't specify which framework can you use but both pThread and boost have implemented that pattern.

Shay Erlichmen
notice the linux tag
Shay Erlichmen
+3  A: 

I suggest a reader-writer lock. The idea is you can acquire a lock for "reading" or for "writing", and the lock will allow multiple readers, but only one writer. Very handy.

asveikau
There is also a queuing principle, so that if a writer ask for access it won't have to wait for a period of non-read, but will delay future read-requests until it has obtained its access and executed its work.
Matthieu M.
+4  A: 

The concept is a "shared reader, single writer" lock as others have stated. In Linux environments you should be able to use pthread_rwlock_t without any framework. I would suggest looking into boost::shared_lock as well.

D.Shawley