{"id":5418,"date":"2022-07-02T00:01:36","date_gmt":"2022-07-02T07:01:36","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=5418"},"modified":"2022-06-25T12:24:15","modified_gmt":"2022-06-25T19:24:15","slug":"chatting-with-a-thread","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=5418","title":{"rendered":"Chatting with a Thread"},"content":{"rendered":"<p>A launched <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5365\">thread<\/a> can be passed an argument, similar to any function. And the thread can <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5393\">return a value<\/a>, just like any function. But while the thread runs, options for communications are rather limited.<br \/>\n<!--more--><br \/>\nOne way to chat with a running thread is to create a pipe, as covered in <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5403\">last week&#8217;s Lesson<\/a>. The pipe is created before the thread is launched, setting input and output file descriptors. The output file descriptor is passed to the thread as an argument, allowing the main program to send data to the thread through the pipe.<\/p>\n<p>The following code demonstrates this process. A thread is created, then it waits for input from the pipe and outputs the result.<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2022_07_02-Lesson.c\" rel=\"noopener\" target=\"_blank\">2022_07_02-Lesson.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#include &lt;string.h&gt;\r\n\r\nvoid *patiently(void *p)\r\n{\r\n    int fd;\r\n    char buffer[BUFSIZ];\r\n\r\n    fd = *(int *)p;\r\n\r\n    while( read(fd,buffer,BUFSIZ) == 0 )\r\n        sleep(1);\r\n    printf(\"The thread has received: %s\",buffer);\r\n\r\n    return(NULL);\r\n}\r\n\r\nint main()\r\n{\r\n    char buffer[BUFSIZ];\r\n    int fp[2];\r\n    pthread_t thd;\r\n    int r;\r\n\r\n    <span class=\"comments\">\/* open the pipe *\/<\/span>\r\n    r = pipe(fp);\r\n    if( r==-1 )\r\n    {\r\n        perror(\"Pipe\");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* spawn the thread, passing it the read\r\n       end of the pipe *\/<\/span>\r\n    r = pthread_create( &amp;thd, NULL, patiently, (void *)&amp;fp[0] );\r\n    if( r!=0 )\r\n    {\r\n        perror(\"Thread\");\r\n        exit(1);\r\n    }\r\n\r\n    <span class=\"comments\">\/* interact with the thread *\/<\/span>\r\n    printf(\"Send some text to the thread: \");\r\n    fgets(buffer,BUFSIZ,stdin);\r\n    write(fp[1],buffer,strlen(buffer));\r\n\r\n    puts(\"Press Enter:\");\r\n    getchar();\r\n\r\n    return(0);\r\n}<\/pre>\n<p>The <em>patiently()<\/em> function is launched as a thread from the <em>main()<\/em> function. Its argument is a <em>void<\/em> pointer, standard for all threads. Internally, this pointer&#8217;s value is saved in <em>int<\/em> variable <code>fd<\/code>. The ugly conversion takes place at Line 11:<\/p>\n<p><code>fd = *(int *)p;<\/code><\/p>\n<p>The <em>void<\/em> pointer <code>p<\/code> must be cast to an <em>int<\/em> pointer <code>(int *)<\/code>, then the <code>*<\/code> operator fetches value at that address, which is stored in variable <code>fd<\/code>. I set this weird-ass construction as its own statement to keep the <em>read()<\/em> function at Line 13 from looking overly complex. Variable <code>fd<\/code> acts as the output file descriptor for the pipe created in the <em>main()<\/em> function. (The output is generated by the <em>main()<\/em> function.)<\/p>\n<p>As the <em>patiently()<\/em> thread is unsynchronized with the <em>main()<\/em> thread (more on this topic at the end of the post), a <em>while<\/em> loop at Line 13 polls the <em>read()<\/em> function. This function returns zero when nothing has been read, so the loop sleeps one second and repeats. A more sophisticated approach would be to use the <em>select()<\/em> or <em>poll()<\/em> functions here, but I didn&#8217;t want this example to go too far into the weeds.<\/p>\n<p>Once data is read, the <em>printf()<\/em> statement at Line 15 outputs the results, then the thread terminates.<\/p>\n<p>In the <em>main()<\/em> program, a pipe is created at Line 28 using <em>int<\/em> array <code>fp[]<\/code>. The <em>patiently()<\/em> function is launched as a thread at Line 37 with the pipe&#8217;s input end file descriptor as its argument. Here&#8217;s the ugly format:<\/p>\n<p><code>(void *)&amp;fp[0]<\/code><\/p>\n<p>The address-of operator <code>&amp;<\/code> is required as <code>fp[0]<\/code> is an integer value, not the entire array. This address must be typecast <em>void<\/em> to be swallowed properly as a <em>pipe()<\/em> function argument.<\/p>\n<p>Line 45 prompts the user for input, gathered at Line 46. Line 47 uses the <em>write()<\/em> function to send the input string through the created pipe to the spawned thread, where it&#8217;s processed.<\/p>\n<p>Here is a sample run:<\/p>\n<p><code>Send some text to the thread: Hello, Mr. Thread!<br \/>\nPress Enter:<br \/>\nThe thread has received: Hello, Mr. Thread!<\/code><\/p>\n<p>The <code>Press Enter<\/code> prompt the <em>main()<\/em> function outputs appears before the thread&#8217;s output (at least on my system). This behavior illustrates how the two threads are unsynchronized, which is an issue when communicating with any thread.<\/p>\n<p>It&#8217;s possible to synchronize activity in a thread, as well as provide interprocess communications, by using semaphores and mutexes. I may cover these topics in the future, but be aware that successful communications with a thread should involve some level of synchronization, which is why these extra techniques are available.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A thread not be all lonely in space while it runs. <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=5418\">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-5418","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\/5418","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=5418"}],"version-history":[{"count":3,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5418\/revisions"}],"predecessor-version":[{"id":5431,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/5418\/revisions\/5431"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5418"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5418"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5418"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}