Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing string as Thread start routine parameter : C++

Referring to http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html#SCHEDULING

I am trying to create two threads in C++ and trying to pass the string as parameter to the Thread Start Routine. The Thread Start Routine parameter can only be (void *) type as per definition:

int pthread_create(pthread_t * thread, 
                       const pthread_attr_t * attr,
                       void * (*start_routine)(void *), 
                       void *arg);

But I get below error:

$ make
g++ -g -Wall Trial.cpp -o Trial
Trial.cpp: In function `int main()':
Trial.cpp:22: error: cannot convert `message1' from type `std::string' to type `void*'
Trial.cpp:23: error: cannot convert `message2' from type `std::string' to type `void*'
Makefile:2: recipe for target `Trial' failed
make: *** [Trial] Error 1

The code is

#include <iostream>
#include <pthread.h>
#include <string>



using namespace std;

void *print_message_function( void *ptr );


int main()
{
    pthread_t thread1, thread2;

    string message1 = "Thread 1";
    string message2 = "Thread 2";

    int  iret1, iret2;


     iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
     iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);



     pthread_join( thread1, NULL);
     pthread_join( thread2, NULL);



     cout << "Thread 1 returns: " <<  iret1 << endl;
     cout << "Thread 2 returns: " << iret2 << endl;


    return 0;
    }
void *print_message_function( void *ptr )

{
     cout << endl <<  ptr << endl;
     //return 0;

}

Is there any way to pass string as (void *) parameter ? Or Only C style strings can be used as Multithreading parameters - as given in the reference code at the link.

like image 741
Gaurav K Avatar asked May 04 '26 05:05

Gaurav K


2 Answers

The argument needs to be a pointer, and you try to pass an object to it.

You have two choices, either pass a pointer to the std::string object, or pass a pointer to the underlying string. I recommend the first:

 iret1 = pthread_create(&thread1, NULL, print_message_function, &message1);

Then you have to modify the thread function, as otherwise it will print the pointer and not the string it points to:

void* print_message_function(void* ptr)
{
    std::string str = *reinterpret_cast<std::string*>(ptr);

    std::cout << str << std::endl;

    return nullptr;
}

Unless it's a requirement to use POSIX threads, I would actually rather recommend the threading functionality in the C++ standard library:

#include <iostream>
#include <string>
#include <thread>

void print_message_function(const std::string& msg);

int main()
{
    std::string message1 = "Thread 1";
    std::string message2 = "Thread 2";

    std::thread thread1(print_message_function, std::cref(message1));
    std::thread thread2(print_message_function, std::cref(message2));

    thread1.join();
    thread2.join();
}

void print_message_function(const std:string& msg)
{
    std::cout << msg << std::endl;
}
like image 94
Some programmer dude Avatar answered May 06 '26 17:05

Some programmer dude


You can pass any arguments to the pthread_create method by wrapping all the arguments into simple structure. For example:

struct ThreadParams {
    std::vector<int> ints;
    std::string clientName;
    // more params
};

All you need to do is to initialize this structure before calling CreateThread function, and then pass a pointer:

ThreadParams * params = new ThreadParams();
params.setParameters();
pthread_create(..., params);

void* print_message_function(void* arg)
    ThreadParams * params = reinterpret_cast<ThreadParams *>(arg);
    // delete after usage;
    delete params;
}
like image 37
nogard Avatar answered May 06 '26 18:05

nogard