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 ----------------------- |