c++g++pthreadspthread-join

Trouble calling function via pthread


I have a function that counts the number of occurences of a string in a char array. Calling this function normally with findword(copy, "polar") works perfectly fine and prints an int that's the number of times the string "polar" occurs in the char array "copy". Calling the function via a pthread however gives me compilation issues and I don't know why. This is my first time implementing multithreading.

Here is the function I want to call:

void findword(char *str, string word)
{
    char *p;
    vector<string> a;
  
    p = strtok(str, " ");
    while (p != NULL)
    {
        a.push_back(p);
        p = strtok(NULL, " ");
    }

    int c = 0;
    for (int i = 0; i <= a.size(); i++)
  
        
        if (word == a[i])
            c++;
    printf("%d", c);
}

And here is the thread I'm trying to create that is supposed to call the function:

struct findwordargs {
  char *str;
  string word;
};

struct findwordargs firstwordArguments;
firstwordArguments.str = copy;
firstwordArguments.word = "polar";

pthread_t thread_id = 1;
pthread_create(&thread_id, NULL, findword, (void *)(&firstwordArguments));
pthread_join(thread_id, NULL);


whenever I compile using g++ and the -pthread flag I get this compile error:


error: invalid conversion from ‘int (*)(char*, std::string)’ {aka ‘int (*)(char*, std::__cxx11::basic_string<char>)’} to ‘void* (*)(void*)’ [-fpermissive]
  101 | pthread_create(&thread_id, NULL, findword, (void *)(&firstwordArguments));

All the necessary header files are included, thank you for the help.


Solution

  • Your findword() function does not match the signature that pthread_create() requires:

    void *(*start_routine)(void *) 
    

    Try this instead:

    struct findwordargs
    {
        char *str;
        std::string word;
    };
    
    void* findword(void *param)
    {
        findwordargs *args = static_cast<findwordargs*>(param);
        std::vector<std::string> a;
    
        char *p = strtok(args->str, " ");
        while (p) {
            a.push_back(p);
            p = strtok(NULL, " ");
        }
        int c = 0;
        for (size_t i = 0; i < a.size(); ++i) {
            if (args->word == a[i])
                c++;
        }
        printf("%d", c);
    
        /* alternatively, using more C++-ish routines:
        std::istringstream iss(args->str);
        std::string word;
        while (iss >> word) a.push_back(word);
        std::cout << std::count(a.begin(), a.end(), args->word);
        */
    
        return NULL;
    }
    
    ...
    
    findwordargs firstwordArguments;
    firstwordArguments.str = copy;
    firstwordArguments.word = "polar";
    
    pthread_t thread_id = 1;
    pthread_create(&thread_id, NULL, findword, &firstwordArguments);
    pthread_join(thread_id, NULL); 
    

    That being said, there is no point in creating a thread just to immediately join it. That blocks the calling thread until the spawned thread exits, which is the same effect as simply calling the function directly, but without the overhead of context switching between threads:

    void findword(const std::string &str, const std::string &word)
    {
        std::vector<std::string> a;
        std::istringstream iss(str);
        std::string word;
        while (iss >> word) a.push_back(word);
        std::cout << std::count(a.begin(), a.end(), word);
    }
    
    ...
    
    findword(copy, "polar");