Patrick Loney:
I've got some objects which are stored in a DB that are being used in a
multi-threaded application. I'm trying to avoid loading the same object
from the db and would like the added bonus of changes made by one thread
being instantly available to all others (with suitable mutex protection
provided during a change but they are predominantly read-only)
...
The shared_ptr portion is easy: you can use a map
as a cache:
static map s_cache;
shared_ptr<Record> get_object( string id )
{
if( shared_ptr<Record> pr = s_cache[ id ].lock() )
{
return pr;
}
shared_ptr<Record> pr2( new Record( id ) );
s_cache[ id ] = pr2;
return pr2;
}
The synchronization that would make this suitably thread-safe is harder
though. You need to protect s_cache with a mutex. You need to protect
modifications to a particular Record with a mutex. Finally, if ~Record
writes to the database, you have to protect against the race that occurs
when the last shared_ptr<Record> to record "X" dies, which enters ~Record,
and another thread enters get_object("X"), loading the old state of "X"
before ~Record has had the chance to update it. I'm not sure if this race is
solvable, so it might be better to write to the DB in a separate
Record::update method(s) while the shared_ptr is still alive.