Author: wyoung
Date: Thu Mar 5 19:57:10 2009
New Revision: 2479
URL: http://svn.gna.org/viewcvs/mysqlpp?rev=2479&view=rev
Log:
Several minor clarity and correctness tweaks to threads chapter.
Modified:
trunk/doc/userman/threads.dbx
Modified: trunk/doc/userman/threads.dbx
URL:
http://svn.gna.org/viewcvs/mysqlpp/trunk/doc/userman/threads.dbx?rev=2479&r1=2478&r2=2479&view=diff
==============================================================================
--- trunk/doc/userman/threads.dbx (original)
+++ trunk/doc/userman/threads.dbx Thu Mar 5 19:57:10 2009
@@ -25,14 +25,13 @@
consequences. Everything else is up to you, the programmer, to
evaluate and enable as and when you need it.</para>
- <para>We’re going to assume that you either agree with these
- views but find yourself needing to use threads for some other
- reason, or are foolishly disregarding these facts and are going to
- use threads anyway. Our purpose here is limited to setting down
- the rules for avoiding problems with MySQL++ in a multi-threaded
- program. We won’t go into the broader issues of thread safety
- outside the scope of MySQL++. You will need a grounding in threads
- in general to get the full value of this advice.</para>
+ <para>We’re going to assume that you are reading this chapter
+ because you find yourself needing to use threads for some other
+ reason than to speed up MySQL access. Our purpose here is limited
+ to setting down the rules for avoiding problems with MySQL++ in a
+ multi-threaded program. We won’t go into the broader issues of
+ thread safety outside the scope of MySQL++. You will need a grounding
+ in threads in general to get the full value of this advice.</para>
<sect2 id="thread-build">
<title>Build Issues</title>
@@ -77,11 +76,12 @@
thread-safe one. (The “<filename>_r</filename>”
means reentrant.)</para>
- <para>If you’re using the Windows binary distribution of
- MySQL, there are two versions of the client library, but both
- are thread aware. One just has debugging symbols, and the other
- doesn’t. See <filename>README-Visual-C++.txt</filename>
- or <filename>README-MinGW.txt</filename> for details.</para>
+ <para>If you’re using the Windows binary distribution
+ of MySQL, you should have only one version of the C
+ API library, which should be thread-aware. If you have
+ two, you probably just have separate debug and optimized
+ builds. See <filename>README-Visual-C++.txt</filename> or
+ <filename>README-MinGW.txt</filename> for details.</para>
<para>If you build MySQL from source, you might only get
one version of the MySQL C API library, and it can have
@@ -224,48 +224,42 @@
<para>You can call
<methodname>Connection::thread_aware()</methodname> to
- determine whether MySQL++ and the underlying C API library
- were both built to be thread-aware. Again, I stress that thread
+ determine whether MySQL++ and the underlying C API library were
+ both built to be thread-aware. I want to stress that thread
<emphasis>awareness</emphasis> is not the same thing as thread
- <emphasis>safety</emphasis>: it’s still up to you to
- make your code thread-safe. If this method returns true, it
- just means it’s <emphasis>possible</emphasis> to achieve
- thread-safety.</para>
-
- <para>If your program’s connection-management strategy allows
- a thread to use a <classname>Connection</classname> object that
- another thread created before it creates a connection of its own,
- you must call <methodname>Connection::thread_start()</methodname>
- from that thread before it does anything with MySQL++. If a
- thread creates a new connection before it uses a connection
- created by another thread, though, it doesn’t need to call
- <methodname>Connection::thread_start()</methodname> because the
- per-thread resources this allocates are implicitly created upon
- creation of a connection if necessary.</para>
-
- <para>This is why the simple
- <classname>Connection</classname>-per-thread strategy
- works: each thread that uses MySQL++ creates a connection
- in that thread, implicitly allocating the per-thread
- resources at the same time. You never need to call
- <methodname>Connection::thread_start()</methodname> in this
- instance. It’s not harmful to call this function, just
- unnecessary.</para>
-
- <para>A good counterexample is using
- <classname>ConnectionPool</classname>: you probably do need
- to call <methodname>Connection::thread_start()</methodname>
- at the start of each worker thread because you can’t
- usually tell whether you’re getting a new connection
- from the pool, or reusing one that another thread returned
- to the pool after allocating it. It’s possible to
- conceive of situations where you can guarantee that each pool
- user always allocates a fresh connection the first time it
- calls <methodname>ConnectionPool::grab()</methodname>,
- but thread programming is complex enough that
- it’s best to take the safe path and always call
- <methodname>Connection::thread_start()</methodname> early in each
- worker thread.</para>
+ <emphasis>safety</emphasis>: it’s still up to you to make
+ your code thread-safe. If this method returns true, it just means
+ it’s <emphasis>possible</emphasis> to achieve thread-safety,
+ not that you actually have it.</para>
+
+ <para>If your program’s connection-management strategy
+ allows a thread to use a <classname>Connection</classname>
+ object that another thread created, you need to know
+ about <methodname>Connection::thread_start()</methodname>.
+ This function sets up per-thread resources needed to make MySQL
+ server calls. You don’t need to call it when you use the
+ simple <classname>Connection</classname>-per-thread strategy,
+ because this function is implicitly called the first time you
+ create a <classname>Connection</classname> in a thread. It’s
+ not harmful to call this function from a thread that previously
+ created a <classname>Connection</classname>, just unnecessary. The
+ only time it’s necessary is when a thread can make calls
+ to the database server on a <classname>Connection</classname>
+ that another thread created and that thread hasn’t already
+ created a <classname>Connection</classname> itself.</para>
+
+ <para>If you use <classname>ConnectionPool</classname>, you should
+ call <methodname>thread_start()</methodname> at the start of each
+ worker thread because you probably can’t reliably predict
+ whether your <methodname>grab()</methodname> call will create a new
+ <classname>Connection</classname> or will return one previously
+ returned to the pool from another thread. It’s possible
+ to conceive of situations where you can guarantee that each pool
+ user always creates a fresh <classname>Connection</classname> the
+ first time it calls <methodname>grab()</methodname>, but thread
+ programming is complex enough that it’s best to take the
+ safe path and always call <methodname>thread_start()</methodname>
+ early in each worker thread.</para>
<para>Finally, there’s the complementary method,
<methodname>Connection::thread_end()</methodname>. Strictly
@@ -287,23 +281,26 @@
<title>Sharing MySQL++ Data Structures</title>
<para>We’re in the process of making it safer to share
- MySQL++’s data structures across threads.</para>
-
- <para>By way of illustration, let me explain a problem we had up
- until MySQL++ v3.0. When you issue a database query that returns
- rows, you also get information about the columns in each row. Since
- the column information is the same for each row in the result set,
- older versions of MySQL++ kept this information in the result set
- object, and each <ulink url="Row" type="classref"/> kept a pointer
- back to the result set object that created it so it could access
- this common data at need. This was fine as long as each result set
- object outlived the <classname>Row</classname> objects it returned.
- It required uncommon usage patterns to run into trouble in this area
- in a single-threaded program, but in a multi-threaded program it was
- easy. For example, there’s frequently a desire to let one
- connection do the queries, and other threads process the results.
- You can see how avoiding lifetime problems here would require a
- careful locking strategy.</para>
+ MySQL++’s data structures across threads. Although things
+ are getting better, it’s highly doubtful that all problems
+ with this are now fixed. By way of illustration, allow me explain
+ one aspect of this problem and how we solved it in MySQL++
+ 3.0.0.</para>
+
+ <para>When you issue a database query that returns rows, you
+ also get information about the columns in each row. Since the
+ column information is the same for each row in the result set,
+ older versions of MySQL++ kept this information in the result
+ set object, and each <ulink url="Row" type="classref"/> kept
+ a pointer back to the result set object that created it so it
+ could access this common data at need. This was fine as long as
+ each result set object outlived the <classname>Row</classname>
+ objects it returned. It required uncommon usage patterns to run
+ into trouble in this area in a single-threaded program, but in
+ a multi-threaded program it was easy. For example, there’s
+ frequently a desire to let one connection do the queries, and other
+ threads process the results. You can see how avoiding lifetime
+ problems here would require a careful locking strategy.</para>
<para>We got around this in MySQL++ v3.0 by giving these shared data
structures a lifetime independent of the result set object that
@@ -312,12 +309,12 @@
<para>Although this is now a solved problem, I bring it up because
there are likely other similar lifetime and sequencing problems
- waiting to be discovered inside MySQL++. If you would like to help
- us find these, by all means, share data between threads willy-nilly.
- We welcome your crash reports on the MySQL++ mailing list. But if
- you’d prefer to avoid problems, it’s better to keep all
- data about a query within a single thread. Between this and the
- previous section’s advice, you should be able to use threads
- with MySQL++ without trouble.</para>
+ waiting to be discovered inside MySQL++. If you would like to
+ help us find these, by all means, share data between threads
+ willy-nilly. We welcome your crash reports on the MySQL++
+ mailing list. But if you’d prefer to avoid problems,
+ it’s better to keep all data about a query within a single
+ thread. Between this and the advice in prior sections, you should
+ be able to use threads with MySQL++ without trouble.</para>
</sect2>
</sect1>
_______________________________________________
Mysqlpp-commits mailing list
[email protected]
https://mail.gna.org/listinfo/mysqlpp-commits