Cleaner way of working with a shared resource?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Mar 29 18:07:50 UTC 2018


On Thursday, March 29, 2018 17:41:15 Chris M. via Digitalmars-d-learn wrote:
> I'm working with mysql-native for a project, and have been using
> a single, shared Connection
> (http://semitwist.com/mysql-native-docs/v2.2.0/mysql/connection/Connection
> .html) among multiple threads. The issue here is that since it's shared, I
> can't use certain functions such as exec() or close() since they're not
> shared.
>
> I've been doing the following as a workaround. It's not a huge
> deal to do, but is this the best way to accomplish this? Short of
> going through the library and making the functions shared myself
> of course.
>
> shared Connection con = ...;
>
> void closeDatabase()
> {
>      synchronized
>      {
>          auto _con = cast(Connection) con;
>
>          if (!_con.closed)
>              _con.close();
>      }
> }

In general, the correct way to deal with a shared object is to protect
access to it with a mutex and then within that protected section, you cast
away shared so that it's treated as thread-local so that it can be operated
on. Then when you release the mutex, you make sure that no thread-local
references to the shared object persist. Most operations really aren't
supposed to work while the object is treated as shared, because then you
have a threading problem if the operation is non-atomic and doesn't protect
itself with a mutex (though a member function on an object certainly could
use a mutex internally, allowing it to be shared and work on a shared
object).

So, assuming that access to the Connection is properly protected by the code
in general, what you're doing is correct, but if you're not using the same
mutex for that operation as for other operations on Connection, and other
code could be operating on the Connection at the same time, then you have a
problem. At the moment, I don't remember where a synchronized block with no
argument gets its mutex, so I'm not sure which mutex you're using. However,
since Connection appears to be a class, it has a built-in monitor object,
meaning that it should work to just do

synchronized(con)
{
}

and use the Connection object's own internal mutex to lock it. So, if you do
that whenever you have to operate on the Connection object, then you know
that you're using the same mutex in all cases.

And, of course, if it helps, you can create a wrapper struct or class around
the Connection object and have the wrapper type handle all of the locking
and casting for you.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list