简体   繁体   中英

main doesn't continue after call pthread_join function

I'm new to pthread and multithreading, i have written a code like that.

#include <pthread.h>
#include <unistd.h>


void *nfc_read(void *arg)
{
    int fd = -1;   
    int ret;
    uint8_t read_data[24];

    while(1){
        ret = read_block(fd, 8, read_data);
        if(!ret){
            return (void)read_data;
        }
    }
}

int main(int argc, char *argv[])
{
    pthread_t my_thread;
    void  *returnValue;

    pthread_create(&my_thread, NULL, nfc_read, NULL);
    pthread_join(my_thread, &returnValue);

    printf("NFC card value is : %s \n", (char)returnValue);

    printf("other process");

  return 0;
}

Until the return value from nfc_read function, as I will have other code I need to run and I don't want to block in main. How can i do that?

This is a sample where a read thread runs concurrently to the "main" thread which is doing other work (in this case, printing dots and sleeping).

To keep things simple, a simulated the reading from an input device with copying a constant string character by character. I guess, this is reasonable as the synchronization of threads is focused.

For the synchronization of threads, I used atomic_bool with atomic_store() and atomic_load() which are provided by the Atomic Library (since C11).

My sample application test-concurrent-read.c :

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdatomic.h>
#include <unistd.h>

/* sampe input */
const char sampleInput[]
  = "This is sample input which is consumed as if it was read from"
    " a (very slow) external device.";

atomic_bool readDone = ATOMIC_VAR_INIT(0);

void* threadRead(void *pArg)
{
  char **pPBuffer = (char**)pArg;
  size_t len = 0, size = 0;
  int c; const char *pRead;
  for (pRead = sampleInput; (c = *pRead++) > 0; sleep(1)) {
    if (len + 1 >= size) {
      if (!(*pPBuffer = realloc(*pPBuffer, (size + 64) * sizeof(char)))) {
        fprintf(stderr, "ERROR! Allocation failed!\n");
        break;
      }
      size += 64;
    }
    (*pPBuffer)[len++] = c; (*pPBuffer)[len] = '\0';
  }
  atomic_store(&readDone, 1);
  return NULL;
}

int main()
{
  /* start thread to read concurrently */
  printf("Starting thread...\n");
  pthread_t idThreadRead; /* thread ID for read thread */
  char *pBuffer = NULL; /* pointer to return buffer from thread */
  if (pthread_create(&idThreadRead, NULL, &threadRead, &pBuffer)) {
    fprintf(stderr, "ERROR: Failed to start read thread!\n");
    return -1;
  }
  /* start main loop */
  printf("Starting main loop...\n");
  do {
    putchar('.'); fflush(stdout);
    sleep(1);
  } while (!atomic_load(&readDone));
  putchar('\n');
  void *ret;
  pthread_join(idThreadRead, &ret);
  /* after sync */
  printf("\nReceived: '%s'\n", pBuffer ? pBuffer : "<NULL>");
  free(pBuffer);
  /* done */
  return 0;
}

Compiled and tested with gcc in cygwin on Windows 10 (64 bit):

$ gcc -std=c11 -pthread -o test-concurrent-read test-concurrent-read.c

$ ./test-concurrent-read
Starting thread...
Starting main loop...
.............................................................................................

Received: 'This is sample input which is consumed as if it was read from a (very slow) external device.'

$ 

I guess, it is worth to mention why there is no mutex guarding for pBuffer which is used in main() as well as in threadRead() .

  1. pBuffer is initialized in main() before pthread_create() is called.

  2. While thread_read() is running, pBuffer is used by it exclusively (via its passed address in pPBuffer ).

  3. It is accessed in main() again but not before pthread_join() which grants that threadRead() has ended.

I tried to find a reference by google to confirm that this procedure is well-defined and reasonable. The best, I could find was SO: pthread_create(3) and memory synchronization guarantee in SMP architectures which cites The Open Group Base Specifications Issue 7 - 4.12 Memory Synchronization .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM