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