|
From: Carlo W. <li...@us...> - 2002-02-18 04:36:20
|
CVSROOT : /cvsroot/libcw
Module : src
Commit time: 2002-01-18 04:36:17 UTC
Modified files:
libcwd/documentation/tutorial/Makefile
libcwd/documentation/tutorial/index.m4
libcwd/documentation/tutorial/tut7.in
Added files:
libcwd/documentation/tutorial/tut8.m4
Log message:
Added tutorial on threading.
---------------------- diff included ----------------------
Index: src/libcwd/documentation/tutorial/Makefile
diff -u src/libcwd/documentation/tutorial/Makefile:1.2 src/libcwd/documentation/tutorial/Makefile:1.3
--- src/libcwd/documentation/tutorial/Makefile:1.2 Sat Dec 29 20:17:49 2001
+++ src/libcwd/documentation/tutorial/Makefile Sun Feb 17 20:36:07 2002
@@ -9,7 +9,7 @@
all: examples html
examples: $(SOURCES5) $(SOURCES7)
-html: index.html faq.html intro.html tut1.html tut2.html tut3.html tut4.html tut5.html tut6.html tut7.html
+html: index.html faq.html intro.html tut1.html tut2.html tut3.html tut4.html tut5.html tut6.html tut7.html tut8.html
%.html: %.m4 ../definitions.m4
m4 -D__TUTORIAL=1 -I.. $< > $@
Index: src/libcwd/documentation/tutorial/index.m4
diff -u src/libcwd/documentation/tutorial/index.m4:1.2 src/libcwd/documentation/tutorial/index.m4:1.3
--- src/libcwd/documentation/tutorial/index.m4:1.2 Sat Dec 29 20:17:49 2001
+++ src/libcwd/documentation/tutorial/index.m4 Sun Feb 17 20:36:07 2002
@@ -9,7 +9,7 @@
</TD>
<TD valign=center><DIV class="toc-header1">
<A class="toc1" href="../html/index.html" target="_top">
- Back to main index
+ back to main index
</A></DIV>
</TD>
</TR>
@@ -62,25 +62,26 @@
__TOC_START
__PAGE(1, [[Introduction]], intro.html)
__PAGE(2, [[Tutorial 1 : Hello World]], tut1.html)
-__PAGE(3, [[Tutorial 2 : Creating your own Debug Channels]], tut2.html)
-__PAGE(4, [[Tutorial 3 : Setting the <CODE>ostream</CODE>]], tut3.html)
-__PAGE(5, [[Tutorial 4 : Management of <CODE>CWDEBUG</CODE>]], tut4.html)
-__PAGE(6, [[Tutorial 5 : Advanced examples]], tut5.html)
+__PAGE(3, [[Tutorial 2 : Creating Your Own Debug Channels]], tut2.html)
+__PAGE(4, [[Tutorial 3 : Setting The <CODE>ostream</CODE>]], tut3.html)
+__PAGE(5, [[Tutorial 4 : Management Of <CODE>CWDEBUG</CODE>]], tut4.html)
+__PAGE(6, [[Tutorial 5 : Advanced Examples]], tut5.html)
__PAGE_START
-__PARAGRAPH(2f, 5.1, [[Running over all Debug Channels]], [[tut5.html#Running]])
-__PARAGRAPH(2, 5.2, [[Debug Channels and name spaces]], [[tut5.html#Debug]])
-__PARAGRAPH(2, 5.3, [[Combining channels]], [[tut5.html#Combining]])
-__PARAGRAPH(2, 5.4, [[Formatting debug output]], [[tut5.html#Formatting]])
-__PARAGRAPH(3, 5.4.1, [[Control flags]], [[tut5.html#Control]])
-__PARAGRAPH(3, 5.4.2, [[Methods of the debug object]], [[tut5.html#Methods]])
+__PARAGRAPH(2f, 5.1, [[Running Over All Debug Channels]], [[tut5.html#Running]])
+__PARAGRAPH(2, 5.2, [[Debug Channels And Name Spaces]], [[tut5.html#Debug]])
+__PARAGRAPH(2, 5.3, [[Combining Channels]], [[tut5.html#Combining]])
+__PARAGRAPH(2, 5.4, [[Formatting Debug Output]], [[tut5.html#Formatting]])
+__PARAGRAPH(3, 5.4.1, [[Control Flags]], [[tut5.html#Control]])
+__PARAGRAPH(3, 5.4.2, [[Methods Of The Debug Object]], [[tut5.html#Methods]])
__PAGE_END
-__PAGE(7, [[Tutorial 6 : The debugging of dynamic memory allocations]], tut6.html)
-__PAGE(8, [[Tutorial 7 : Advanced examples]], tut7.html)
+__PAGE(7, [[Tutorial 6 : The Debugging Of Dynamic Memory Allocations]], tut6.html)
+__PAGE(8, [[Tutorial 7 : Advanced Examples]], tut7.html)
__PAGE_START
-__PARAGRAPH(2f, 7.1, [[Removing allocations from the Allocated memory Overview]], [[tut7.html#Removing]])
-__PARAGRAPH(2, 7.2, [[Retrieving information about memory allocations]], [[tut7.html#Retrieving]])
-__PARAGRAPH(2, 7.3, [[Memory leak detection]], [[tut7.html#Memory]])
+__PARAGRAPH(2f, 7.1, [[Removing Allocations From The Allocated Memory Overview]], [[tut7.html#Removing]])
+__PARAGRAPH(2, 7.2, [[Retrieving Information About Memory Allocations]], [[tut7.html#Retrieving]])
+__PARAGRAPH(2, 7.3, [[Memory Leak Detection]], [[tut7.html#Memory]])
__PAGE_END
+__PAGE(9, [[Tutorial 8 : Debugging Threaded Applications]], tut8.html)
__TOC_END
__PAGEEND
__PAGEFOOTER
Index: src/libcwd/documentation/tutorial/tut7.in
diff -u src/libcwd/documentation/tutorial/tut7.in:1.2 src/libcwd/documentation/tutorial/tut7.in:1.3
--- src/libcwd/documentation/tutorial/tut7.in:1.2 Sat Dec 29 20:17:49 2001
+++ src/libcwd/documentation/tutorial/tut7.in Sun Feb 17 20:36:07 2002
@@ -495,14 +495,12 @@
<!-- START OUTPUT examples7/test7.3.5-bin -->
</PRE>
-<P>Congratulations, you are now a libcwd expert. If you still have any
-questions that you can't find here, feel free to mail me.</P>
-
__PAGEEND
-<P class="line"><IMG width=870 height=25 src="../images/lines/owl.png"></P>
+<P class="line"><IMG width=870 height=19 src="../images/lines/hippo.png"></P>
<DIV class="buttons">
<A HREF="tut6.html"><IMG width=64 height=32 src="../images/buttons/lr_prev.png" border="0"></A>
<A HREF="index.html"><IMG width=64 height=32 src="../images/buttons/lr_index.png" border="0"></A>
+<A HREF="tut8.html"><IMG width=64 height=32 src="../images/buttons/lr_next.png" border="0"></A>
</DIV>
__PAGEFOOTER
__HTMLFOOTER
Index: src/libcwd/documentation/tutorial/tut8.m4
diff -u /dev/null src/libcwd/documentation/tutorial/tut8.m4:1.1
--- /dev/null Sun Feb 17 20:36:17 2002
+++ src/libcwd/documentation/tutorial/tut8.m4 Sun Feb 17 20:36:07 2002
@@ -0,0 +1,121 @@
+include(definitions.m4)dnl
+__HTMLHEADER
+__PAGEHEADER
+__PAGESTART
+
+<H2>Tutorial 8: Debugging Threaded Applications</H2>
+
+<P>Libcwd should be completely thread-safe, with the following restrictions:</P>
+<UL>
+<LI>All debug objects and debug channels <EM>must</EM> be global (as they should
+be in non-threaded applications for that matter).</LI>
+<LI>You are not allowed to create threads before all static and global objects
+are initialized; in practise this means that you are not allowed to create threads
+until <CODE>main()</CODE> is reached.</LI>
+<LI>You cannot use <CODE>dlopen()</CODE> to load libcwd when threads have
+already been created. Likewise you shouldn't <CODE>dlopen()</CODE>
+other libraries that use libcwd when there are already running threads,
+especially when those libraries define new debug objects and/or channels.</LI>
+<LI>You need to provide one and only one locking mechanism per ostream device
+that is also used to write debug output. It is preferable not to
+use the same ostream with two or more different debug objects.</LI>
+</UL>
+
+<P>Essentially the debug objects and channels react towards each thread as if
+that thread is the only thread. The only (visible) shared variable is
+the final <CODE>ostream</CODE> that a given debug object writes to.
+This means that if one thread changes the <CODE>ostream</CODE> then all other
+threads also suddenly start to write to that <CODE>ostream</CODE>.
+Basically, it is simply not supported: don't change the output stream
+on the fly.</P>
+
+<P>All other characteristics like the on/off state and the margin and
+marker strings as well as the indentation are Thread Specific: Every
+thread may change those without locking or worrying about the effect on
+other threads.</P>
+
+<P>Every time a new thread is created, it will start with all debug objects
+and channels turned off, just as at the start of <CODE>main()</CODE>.</P>
+
+<P>In all likelihood, you'd want to set the margin string such that it reflects which
+thread is printing the output. For example:</P>
+
+<PRE>
+void* thread_function(void* arguments)
+{
+ // Set Thread Specific on/off flags of the debug channels.
+ ForAllDebugChannels( if (!debugChannel.is_on()) debugChannel.on(); );
+ // And for the debug object.
+ Debug( libcw_do.on() );
+ // Set a margin.
+#ifdef CWDEBUG
+ char margin[16];
+ sprintf(margin, "%-10lu ", pthread_self());
+#endif
+ Debug( libcw_do.margin().assign(margin, 11) );
+
+ Dout(dc::notice, "Entering thread " << pthread_self());
+ // ... do stuff
+ Dout(dc::notice, "Leaving thread " << pthread_self());
+ return NULL;
+}
+
+int main(void)
+{
+ // Don't output a single character at a time (yuk)
+ // (Read <A HREF ="http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8">http://gcc.gnu.org/onlinedocs/libstdc++/27_io/howto.html#8</A> for an explanation.)
+ std::ios::sync_with_stdio(false);
+ // Do header files and library match?
+ Debug( check_configuration() );
+ // Send debug output to std::cout.
+#ifdef CWDEBUG
+ pthread_mutex_t cout_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+ Debug( libcw_do.set_ostream(&std::cout, &cout_mutex) );
+ // Turn debug object on.
+ Debug( libcw_do.on() );
+ // Set a margin.
+#ifdef CWDEBUG
+ char margin[16];
+ sprintf(margin, "%-10lu ", pthread_self());
+#endif
+ Debug( libcw_do.margin().assign(margin, 11) );
+ // Turn all debug channels on.
+ ForAllDebugChannels( if (!debugChannel.is_on()) debugChannel.on(); );
+ // List all channels.
+ Debug( list_channels_on(libcw_do) );
+
+ // Create and join a few threads...
+ int const number_of_threads = 4;
+ pthread_t thread_id[number_of_threads];
+ for (int i = 0; i < number_of_threads; ++i)
+ {
+ Dout(dc::notice|continued_cf, "main: creating thread " << i << ", ");
+ pthread_create(&thread_id[i], NULL, thread_function, NULL);
+ Dout(dc::finish, "id " << thread_id[i] << '.');
+ }
+
+ for (int i = 0; i < number_of_threads; ++i)
+ {
+ void* status;
+ pthread_join(thread_id[i], &status);
+ Dout(dc::notice, "main loop: thread " << i << ", id " << thread_id[i] <<
+ ", returned with status " << ((bool)status ? "OK" : "ERROR") << '.');
+ }
+
+ Dout(dc::notice, "Exiting from main()");
+ return 0;
+}
+</PRE>
+
+<P>Congratulations, you are now a libcwd expert. If you still have any
+questions that you can't find answers to here, feel free to mail me.</P>
+
+__PAGEEND
+<P class="line"><IMG width=870 height=25 src="../images/lines/owl.png"></P>
+<DIV class="buttons">
+<A HREF="tut7.html"><IMG width=64 height=32 src="../images/buttons/lr_prev.png" border="0"></A>
+<A HREF="index.html"><IMG width=64 height=32 src="../images/buttons/lr_index.png" border="0"></A>
+</DIV>
+__PAGEFOOTER
+__HTMLFOOTER
----------------------- End of diff -----------------------
|