2

My case is similar to another Question.

I would like to pass a function as argument and an integer value. Testing the case with a simplfied construction:

void print (int x, int y) 
{ cout << "x = " << x << ", y = " << y << endl; }

void *interrupt (struct arg_struct args);

struct arg_struct { 
    void (*func)(int,int);          // Argument 1
    int a;                          // Argument 2
    int b;                          // Argument 3
};  

int _tmain(int argc, _TCHAR* argv[]){ 

    int a = 1700, b = 1000;

    struct arg_struct arguments;

    arguments.func = print;
    arguments.a = a;
    arguments.b = b;

    (*interrupt)(arguments);

    cin.get(); return 0;
}


void *interrupt (struct arg_struct args) {

    void (*func) (int,int) ;

    func =  args.func;
    int x = args.a;
    int y = args.b;

    (*func)(x,y);

    return 0;           // Erfordert Rückgabewert
}

So now I want to create a thread to execute this passed function.

void *InThread_func(struct arg_struct *);   // Prototype                        

struct arg_struct { 
    void (*func)(int);          // Argument 1
    int IntNumber;              // Argument 2
};

int InThread(void (*func)(int), int IntNumber){
    
    struct arg_struct arguments;
    
    arguments.func   = func;
    arguments.IntNumber = IntNumber;

    // Initialize handler
    pthread_t InThread_thread;
    
    // Create thread
    pthread_create(&InThread_thread,NULL,&InThread_func,(void*) &arguments);
    
    pthread_join(InThread_func,NULL);

    return(errno);
}

Using

g++-4.6 -o test test.cpp

the compiler says

invalid conversion from void* (*)(arg_struct*) to void * (*)(void*)

referring to the last argument of pthread_create.

Why is that?

2 Answers 2

1

C++ is picky when it comes to casting.

Replace void *InThread_func(struct arg_struct *); by void *InThread_func(void *my_data); and it should solve the problem.

Since this is C++ I'd recommend using std::thread is those are available to you.

Sign up to request clarification or add additional context in comments.

5 Comments

Now I used std::thread and the compiler option -pthread and it works. Thanks. =) Could you tell me in a few words the main differences between those to ways to implement it? Do you have more freedom to optimize the code with pthread_t?
pthread stands for for Posix Thread. It's a *NIX thing. It's not portable (even though there seems to be a pthread port for Windows). std::thread is standard. It will work on all platform your code compile on. The main difference is portability (and ease of use, but that's my opinion). About freedom to optimize: you can retrieve the native handler from a std::thread, so you can do whatever you would have done with a pthread_t.
@Xaqq Re std::thread, the "ease of use" depends partially on what you are doing in the thread, and comes at some cost. Most of the time, I'd recommend them as well, if only for portability, but there are cases where they may not be appropriate. (For large scale servers, for example, Unix is pretty much the only game in town, and the performance issues may be significant.)
@JamesKanze But aren't std::thread implemented with pthread on Unix? If so, how can the performance difference be large enough to be noticed? Would have a link to some article talking about this, it seems rather interesting :)
@Xaqq std::thread will, obviously, use pthread_create at some point. std::thread does more, however; it guarantees a value copy of arbitrary arguments. This can only be done once the new thread has actually started execution. Which means some additional synchronization steps after pthread_create: a conditional, perhaps, or at least a mutex. (IIRC, boost::thread used the condition. And when I needed to do something similar in a project without boost, that's the solution I came up with as well.)
1

"Why is that?" Because you have an invalid conversion from void* (*)( arg_struct* ) to void* (*)( void* ), perhaps. The third argument to pthread_create (not the last) must be an extern "C" void* (*)( void* ). (Some compilers will ignore the necessity of the extern "C". They are broken in this regard.) So your InThread_fnc (which I can't find in your code) must be something like:

extern "C" void*
InThread_fnc( void* from_pthread_create )
{
    arg_struct const* p = static_cast< arg_struct const* >( from_pthread_create );
    (*p->func)( p->IntNumber );
    return nullptr;
}

Of course, this only works if the last argument of pthread_create was a arg_struct*. Which corresponds to your case, but beware if you start deriving: passing a new Derived or a &someDerived when the function you start casts to Base* results in undefined behavior.

1 Comment

Thanks. I will try to implement your solution the next days to get a deeper understanding.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.