
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi! I'm trying to create a wrapper around mysql but I have a problem with shared_ptr. Look at the following code: #include <boost/shared_ptr.hpp> #include <iostream> #include <map> struct MYSQL {}; MYSQL* mysql_init() { std::clog << __PRETTY_FUNCTION__ << std::endl; return new MYSQL; } void mysql_close(MYSQL* m) { std::clog << __PRETTY_FUNCTION__ << std::endl; delete m; } class Connection { boost::shared_ptr<MYSQL> m_mysql; public: void connect() { m_mysql.reset(mysql_init(), mysql_close); } bool isConnected() const { return m_mysql.get() != 0; } }; class ConnectionManager { std::map<std::string, Connection> m_connections; public: static ConnectionManager* instance() { static ConnectionManager cm; return &cm; } Connection connection(const std::string& name = "default") { return m_connections[name]; } }; int main() { { Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl; c.connect(); std::clog << "isConnected " << c.isConnected() << std::endl; } Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl; return 0; } And the output is: isConnected 0 MYSQL* mysql_init() isConnected 1 void mysql_close(MYSQL*) isConnected 0 What I don't understand is why shared_ptr calls mysql_close too soon. After all still exists a reference to Connection. I mean, mysql_close should by called when the ConnectionManager singleton is destroyed or am I doing something wrong. - -- Filipe Sousa -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) iD8DBQFDalOEbQdNYqwwwCwRAsNLAJ43BSZTCuraPQ2ouFqGoW/2+JDPDgCeOoQ7 8ZoF4LDO7vQyrPM/Whtx/O8= =iil3 -----END PGP SIGNATURE-----

Filipe Sousa wrote:
int main() { { Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl; c.connect();
This initializes the shared_ptr inside c, but has no effect on the shared_ptr in the ConnectionManager map.
std::clog << "isConnected " << c.isConnected() << std::endl;
std::clog << "isConnected " << ConnectionManager::instance()->connection().isConnected() << std::endl;
}
'c' is destroyed here, along with its shared_ptr, which calls mysql_close.
Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl;
return 0; }
You need to .reset( .. ) the shared_ptr in the map, before returning it from the connection manager.

class Connection { boost::shared_ptr<MYSQL> m_mysql; public: void connect() { m_mysql.reset(mysql_init(), mysql_close); } bool isConnected() const { return m_mysql.get() != 0; } };
class ConnectionManager { std::map<std::string, Connection> m_connections; public: static ConnectionManager* instance() { static ConnectionManager cm; return &cm; } Connection connection(const std::string& name = "default") { return m_connections[name]; } };
int main() { { Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl; c.connect(); std::clog << "isConnected " << c.isConnected() << std::endl; } Connection c = ConnectionManager::instance()->connection(); std::clog << "isConnected " << c.isConnected() << std::endl;
return 0; }
And the output is:
isConnected 0 MYSQL* mysql_init() isConnected 1 void mysql_close(MYSQL*) isConnected 0
What I don't understand is why shared_ptr calls mysql_close too soon. After all still exists a reference to Connection. I mean, mysql_close should by called when the ConnectionManager singleton is destroyed or am I doing something wrong.
Both c and the map item in ConnectionManager have a shared pointer that points to the "same" MYSQL object, a null. Then you reset c to point to something else. This will not reset the shared pointer in ConnectionManager. Your MYSQL obj gets killed as soon as c goes out of scope. Oliver
- -- Filipe Sousa -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux)
iD8DBQFDalOEbQdNYqwwwCwRAsNLAJ43BSZTCuraPQ2ouFqGoW/2+JDPDgCeOoQ7 8ZoF4LDO7vQyrPM/Whtx/O8= =iil3 -----END PGP SIGNATURE----- _______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

Depending on why you are trying to wrap the mysql API you might like to look at wrapper libraries for databases that already exist. There's a list on the (unofficial) Boost wiki (which appears to be down as I write so I can't insert a link). I use the Database Template Library (DTL) which is at http://dtemplatelib.sourceforge.net/ Richard On Thu, 03 Nov 2005 18:14:28 -0000, Filipe Sousa <filipe@ipb.pt> wrote:
Hi!
I'm trying to create a wrapper around mysql but I have a problem with shared_ptr. Look at the following code:

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Richard Jennings wrote:
Depending on why you are trying to wrap the mysql API you might like to look at wrapper libraries for databases that already exist.
There's a list on the (unofficial) Boost wiki (which appears to be down as I write so I can't insert a link). I use the Database Template Library (DTL) which is at http://dtemplatelib.sourceforge.net/
Richard
Looks promising, I'll looking into it but I still need to wrap the full mysql API because I need support for prepared statements[1] and full control over mysql [1] http://dev.mysql.com/doc/refman/4.1/en/c-api-prepared-statements.html - -- Filipe Sousa -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.2 (GNU/Linux) iD8DBQFDazCgbQdNYqwwwCwRAmv4AKCbdFFu3IR70KMuMiFlV+Ns+p6YLgCeKw3N hHeb+UIA9p+omD2G6SYHPtc= =NgSX -----END PGP SIGNATURE-----
participants (4)
-
Filipe Sousa
-
Oliver Schoenborn
-
Peter Dimov
-
Richard Jennings