{"id":5393,"date":"2022-06-11T00:01:54","date_gmt":"2022-06-11T07:01:54","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5393"},"modified":"2022-06-18T07:29:05","modified_gmt":"2022-06-18T14:29:05","slug":"leaving-a-thread-early","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5393","title":{"rendered":"Leaving a Thread Early"},"content":{"rendered":"<p>Threads in your code go off and do their own thing, running independently from other parts of the code. Still, the thread is established as a function in your source code file. Like any function, it can leave early.<br \/>\n<!--more--><br \/>\nYou can use a <em>return<\/em> statement to exit a thread early, but the official way to exit a thread is to use the <em>pthread_exit()<\/em> function:<\/p>\n<p><code>void pthread_exit(void *value_ptr);<\/code><\/p>\n<p>The <code>value_ptr<\/code> argument is a return value, specified as an address. To capture this value, you use the <em>pthread_join()<\/em> function, which was covered in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5376\">last week&#8217;s Lesson<\/a>. This function halts the main thread (or whatever thread it&#8217;s running in), waiting for the spawned thread to finish. It&#8217;s also the only way to capture the spawned thread&#8217;s return value.<\/p>\n<p>The following code launches a thread to output asterisks. The <em>pthread_join()<\/em> function waits for the launched thread to finish &mdash; but the thread exits early after five asterisks are output.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_06_11-Lesson-a.c\" rel=\"noopener\" target=\"_blank\">2022_06_11-Lesson-a.c<\/a><\/h3>\n<pre class=\"screen\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;unistd.h&gt;\r\n#include &lt;pthread.h&gt;\r\n\r\nvoid *thread_funct(void *a)\r\n{\r\n    const int loop=8;\r\n    int x;\r\n\r\n    for( x=0; x&lt;loop; x++ )\r\n    {\r\n        if( x==5 )\r\n            pthread_exit(\"I'm done!\");\r\n        printf(\"*\\n\");\r\n        sleep(1);\r\n    }\r\n\r\n    return(NULL);\r\n}\r\n\r\nint main()\r\n{\r\n    char buffer[BUFSIZ];\r\n    int r;\r\n    pthread_t thd;\r\n    void *retval;\r\n\r\n    <span class=\"comments\">\/* spawn the new thread *\/<\/span>\r\n    r = pthread_create( &amp;thd, NULL, thread_funct, NULL);\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread\");\r\n        exit(1);\r\n    }\r\n    \r\n    <span class=\"comments\">\/* wait for the thread *\/<\/span>\r\n    r = pthread_join( thd, &amp;retval );\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread join\");\r\n        exit(1);\r\n    }\r\n    printf(\"%s\\n\",(char *)retval);\r\n\r\n    <span class=\"comments\">\/* prompt for your name *\/<\/span>\r\n    printf(\"What is your name? \");\r\n    fgets(buffer,BUFSIZ,stdin);\r\n    printf(\"Hello, %s\",buffer);\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The <em>pthread_join()<\/em> function at Line 38 pauses the main thread until the spawned thread runs to completion. The function&#8217;s first argument is the thread handle, <code>thd<\/code>. The second argument is the address of a <em>void<\/em> pointer, <code>retval<\/code>. This is the argument&#8217;s proper data type, which handles any return value.<\/p>\n<p>The launched thread exits early at Line 13 when the value of variable <code>x<\/code> is equal to 5. The <em>pthread_exit()<\/em> function returns the string <code>\"I'm done!\"<\/code>, which is captured by <em>pthread_join()<\/em>. The <em>printf()<\/em> statement at Line 44 outputs the string, casting it from <em>void<\/em> to a <em>char<\/em> pointer. Then the rest of the <em>main()<\/em> function runs.<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<p><code>*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\n*<br \/>\nI'm done!<br \/>\nWhat is your name? Dan<br \/>\nHello, Dan<\/code><\/p>\n<p>If you want to return a value from the thread, say the integer <code>x<\/code>, you must declare it <em>static<\/em>. Then you return the value&#8217;s address. Here&#8217;s the modified version of the <em>thread_funct()<\/em> function that returns the value in <code>x<\/code>:<\/p>\n<pre class=\"screen\">\r\nvoid *thread_funct(void *a)\r\n{\r\n    const int loop=8;\r\n    static int x;\r\n\r\n    for( x=0; x&lt;loop; x++ )\r\n    {\r\n        if( x==5 )\r\n            pthread_exit(&amp;x);\r\n        printf(\"*\\n\");\r\n        sleep(1);\r\n    }\r\n\r\n    return(NULL);\r\n}<\/pre>\n<p>The <em>pthread_join()<\/em> call in the <em>main()<\/em> function need not be modified, as it accepts a <em>void<\/em> pointer as its second argument. You must still, however, typecast the thread&#8217;s returned value (<code>retval<\/code>) when used in the <em>main()<\/em> function. Here&#8217;s the updated <em>printf()<\/em> statement:<\/p>\n<p><code>printf(\"The thread returned value: %d\\n\",*((int *)retval) );<\/code><\/p>\n<p><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_06_11-Lesson-b.c\" rel=\"noopener\" target=\"_blank\">Click here<\/a> to view the full code on GitHub.<\/p>\n<p>So what happens when you replace <em>pthread_exit()<\/em> with a simple <em>return<\/em> statement?<\/p>\n<p>As far as I can tell, the effect appears the same: <code>pthread_exit(\"I'm done!\")<\/code> becomes <code>return(\"I'm done!\")<\/code>, and <code>pthread_exit(&x)<\/code> becomes <code>return(&x)<\/code>. Coders on Stack Overflow write that the Valgrind utility doesn&#8217;t report issues when <em>return<\/em> is used instead of <em>pthread_exit()<\/em>. I know of no further scintillating details on the differences.<\/p>\n<p>In <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5401\">next week&#8217;s Lesson<\/a> I wrap up my thread on multithreading with coverage of the <em>pthread_cancel()<\/em> function.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Just as you can exit a program or function before it&#8217;s complete, you can also exit a thread. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5393\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-5393","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5393","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5393"}],"version-history":[{"count":5,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5393\/revisions"}],"predecessor-version":[{"id":5429,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5393\/revisions\/5429"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5393"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5393"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5393"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}