[odb-users] Global Custom Session in Multi-Threading Application

Boris Kolpackov boris at codesynthesis.com
Thu Jun 11 09:52:45 EDT 2020

韩彬 <seu.hanbin at gmail.com> writes:

> We noticed that after ODB calls the _cache_insert operation in our
> session, the inserted object is still not initialized with the real data
> in db, and according to line 89 in the load method in libodb-pgsql
> <https://git.codesynthesis.com/cgit/odb/libodb-pgsql/tree/odb/pgsql/polymorphic-object-result.txx>,
> actually the inserted object will actually be initialized after the
> _cache_insert operation.  So given that we have two threads load and insert
> the same object to our object map, would one thread end up with an invalid
> object pointer? Or are there any possible issue with my implementation and
> usage of custom session?

Section 11.2, "Custom Sessions" in the manual has some hints on how this
can be implemented. Specifically:

"The _cache_insert() function shall add the object into the object cache and
return its position. The _cache_find() function looks an object up in the
object cache given its id. It returns a NULL pointer if the object is not
found. The _cache_erase() cache management function shall remove the object
from the cache. It is called if the database operation that caused the object
to be inserted (for example, load) failed. Note also that after insertion the
object state is undefined. You can only access the object state (for example,
make a copy or clear a flag) from one of the notification functions discussed

The notification functions are called after an object has been persisted,
loaded, updated, or erased, respectively."

This suggests that you need to hold the lock until one of the notification
functions is called (the custom cache_position type is there exactly so
that you could propagate something like a lock from _cache_insert() to
one of the notification functions).

Note also that if you use a single mutex for this, you will probably
end up with pretty poor performance and also probably won't be able
to have any object pointers (because their loading would trigger a
call to _cache_insert() and a recursive attempt to acquire a lock).
So I would look into a mutex for the map itself and then a pool of
mutexes that are used to protect an object between _cache_insert()
and a notification function call.

As you can see, this is quite tricky.

More information about the odb-users mailing list