Passing and accessing multiple parameters to pthread function - c++

I am a beginner to cpp and threads. Referred to some code snippets in stackoverflow to pass multiple arguments to a pthread function and came up with the below code. I am not sure how to access the struct members inside the function using (void*) pointer passed to it. Can anyone explain?
#include <iostream>
#include <pthread.h>
#include <vector>
using namespace std;
struct a{
vector <int> v1;
int val;
};
void* function(void *args)
{
vector <int>functionvector = (vector <int>)args->v1;
functionvector.push_back(args->val);
return NULL;
}
int main()
{
pthread_t thread;
struct a args;
pthread_create(&thread, NULL, &function, (void *)&args);
pthread_join(thread,NULL);
for(auto it : args.v1)
{
cout<<it;
}
return 0;
}
Getting the error :
error: ‘void*’ is not a pointer-to-object type

You cannot access the members of a until you have cast the void* back to an a*.
void* function(void *ptr)
{
a* args = static_cast<a*>(ptr);
args->v1.push_back(args->val);
return NULL;
}

Related

How to use string to call function in a class?

I hope to use map library to call a function by a string with the function name, I've tested the following example and everything are working well.
#include <string>
#include <iostream>
using namespace std;
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;//
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
int main()
{
buildMap();
callFunc("func1");
return 0;
}
However, as I define all these things in a class, there is a compiler error occur:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &func1;// a value of type cannot be assigned to an entity of type
}
void callFunc(const std::string& str)
{
(*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
I've tried to solve this problem for a couple of hours. Or is there any other way to use string to call function in a class? I will very appreciate if someone can help me. THANKS!!
Your code doesn't work because func1 is a member function and the syntax for member functions is different.
You need a map of member function pointers (offsets)
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
Then you can store the pointer with
strFuncMap["func1"] = &theClass::func1;
And you need an object to call a member function
(this->*strFuncMap[str])();
The final code:
#include <map>
#include <string>
#include <iostream>
using namespace std;
class theClass {
public:
typedef void (theClass::*pFunc)();
map<string, pFunc> strFuncMap;
void func1()
{
printf("this is func1!\n");
}
void buildMap()
{
strFuncMap["func1"] = &theClass::func1;
}
void callFunc(const std::string& str)
{
(this->*strFuncMap[str])();
}
};
int main()
{
theClass a;
a.buildMap();
a.callFunc("func1");
return 0;
}
typedef void (*pFunc)();
This declares pFunc to be the type of function pointers. That is, the type of pointers to functions which exist at the top-level. This excludes member functions, lambda functions, and functors. Consider
using pFunc = std::function<void()>
Now your type will correctly accept anything that can reasonably be interpreted as a callable object. Note that member functions still need to be wrapped in a lambda, since you're closing around this.
strFuncMap["func1"] = [this]() { this->func1(); };

Pointer to a void * function C++

I am trying to call pointer to a void * function inside the main method and the compiler is saying assigning to 'funcptr<g>' from incompatible type 'void *(void *). hello function is actually an argument to pthread_create function. That's why it is void * function. How can I create a function pointer to a void * function?
#include <iostream>
#include <pthread.h>
using namespace std;
template<typename T>
using funcptr = void (*T::*)(void *); // I think it is wrong here.
class m {
public:
template <typename T>
struct my_struct {
funcptr<T> ptr;
};
};
class g {
public:
static void *hello(void *);
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello; // Error here
return 0;
}
How can I create a function pointer to a void * function?
hello is not a member function, but it's a static function.
So your funcptr should be as follows:
// No template needed.
using funcptr = void* (*)(void *)
Note that hello is declared with static, meaning that it's no longer a member function to g.
Static members of a class are not associated with the objects of the class.
So using void (*T::*)(void *) to cull non-member functions is incorrect.
If you're allowed to use a compiler that supports C++11, you don't even need to manually deduct its type anymore, using decltype:
// decltype deducts its exact type for you.
using funcptr = decltype(&g::hello);
class m
{
public:
struct my_struct
{
funcptr ptr;
};
};
FYI, since hello does not have its definition, you might encounter a linkage error. To prevent that, I assumed that there's some implementation inside:
static void *hello(void *)
{
// Meaningless, but..
return nullptr;
}
if you're using C++11, you can use std::function<> which just bothers about the return type and parameters of the function and not where they are defined and what are its type.
Here is the code using std::function<>
#include <iostream>
#include <functional>
#include <pthread.h>
using namespace std;
class m {
public:
template <typename T>
struct my_struct {
function<void*(void*)> ptr;
};
};
class g {
public:
static void *hello(void *) {
cout<<"Hello.."<<endl;
}
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello;
h.ptr(nullptr);
return 0;
}

Get error with struct member field being a function pointer

I need to have struct member being a regular function pointer (not a class member function pointer). Not sure why the compile error. I am running g++ 4.8.4 on Ubuntu 14.04. Thanks.
$ g++ te5.cc
te5.cc: In function ‘int main(int, char**)’:
te5.cc:18:9: error: invalid use of member function (did you forget the ‘()’ ?)
t.func = dum;
^
te5.cc:19:6: error: ‘func’ was not declared in this scope
(t.*func)();
Code snippet
#include <stdio.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef void pfpv(void *obj);
typedef struct {
pfpv func;
void *obj;
} strTimer;
void dum(void* p) {
printf("in dum()\n");
}
int main (int argc, char *argv[]) {
strTimer t;
t.func = dum;
(t.*func)();
return 0;
}
This can be solved by making pfpv a function pointer instead of a function.
#include <stdio.h>
#include <string>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef void (*pfpv)(void *obj);
typedef struct {
pfpv func;
void *obj;
} strTimer;
void dum(void* p) {
printf("in dum()\n");
}
int main (int argc, char *argv[]) {
strTimer t;
t.func = dum;
t.func(0);
return 0;
}
There are several mistakes here.
typedef void (*pfpv)(void *obj); … you'd left out the first *, so pfpv was just a function type, not a function pointer type.
(t.func)(); You'd used pointer-to-member-function call syntax, but your t.func is just a normal function pointer, so use . not .*.
Furthermore, you're not passing any arguments to a function that expects a void*. We can pass nullptr, for now.
Here it is compiling, with those fixes in place.
This whole debacle could have been avoided if you'd used the far simpler std::function:
#include <iostream>
#include <functional>
struct strTimer
{
std::function<void(void*)> func;
void* obj;
};
void dum(void* p)
{
std::cout << "in dum()\n";
}
int main()
{
strTimer t;
t.func = &dum;
(t.func)(nullptr);
}
Live demo
No need for that antiquated C cruft!
Presumably, passing void* as argument is also designed to satisfy some primordial C idiom, perhaps by passing in &t (instead of nullptr) to simulate member functions. You should consider using lambda functions and other modern language features; your program will be much easier to write, maintain and debug.
The problem is your function pointer typedef (it doesn't specify a function pointer). Change it like so:
typedef void (*pfpv)(void *obj);
Also the call of the function pointer is wrong:
(t.func)(&t);
Live Demo

Using functor in pthread_create

What this code do:
Several commands executed to completion(if(current seconds == some seconds) stop).
CommandProcessor(functor) run this commands. Pointer of this class I try to throw to pthread_create.
The question:
It is possible to use class object as callable?
command.h
#ifndef COMMAND_H
#define COMMAND_H
#include <iostream>
#include "commandprocessor.h"
class CommandProcessor;
using namespace std;
class Command
{
static CommandProcessor *commandProcessor;
time_t stopSeconds;
public:
Command(int _stopSeconds);
static void setProcessor(CommandProcessor *_commandProcessor);
void execute();
};
#endif // COMMAND_H
command.cpp
#include "command.h"
CommandProcessor* Command::commandProcessor = NULL;
Command::Command(int _stopSeconds)
{
stopSeconds = _stopSeconds;
}
void Command::setProcessor(CommandProcessor *_commandProcessor)
{
commandProcessor = _commandProcessor;
}
void Command::execute()
{
time_t seconds;
time_t now = time(NULL);
seconds = localtime(&now)->tm_sec;
cout << seconds << endl;
if(seconds != stopSeconds)
commandProcessor->addCommand(this);
}
commandprocessor.h
#ifndef COMMANDPROCESSOR_H
#define COMMANDPROCESSOR_H
#include <list>
#include "command.h"
using namespace std;
class Command;
class CommandProcessor
{
list< Command* > commandsList;
public:
void addCommand(Command *_command);
void operator()();
};
#endif // COMMANDPROCESSOR_H
commandprocessor.cpp
#include "commandprocessor.h"
void CommandProcessor::addCommand(Command *_command)
{
commandsList.push_back(_command);
}
void CommandProcessor::operator()()
{
while(commandsList.size() > 0)
{
Command *command = commandsList.front();
commandsList.pop_front();
command->execute();
}
}
main.cpp
#include <iostream>
#include <pthread.h>
#include "commandprocessor.h"
#define MAX_THREADS 2
using namespace std;
int main(int argc, char **args)
{
CommandProcessor *processor = new CommandProcessor();
Command::setProcessor(processor);
processor->addCommand(new Command(53));
processor->addCommand(new Command(24));
processor->addCommand(new Command(15));
pthread_t threads[MAX_THREADS];
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor(), NULL); // error: 'processor' cannot be used as a function
}
return 0;
}
DISCLAIMER : this is the kind of thing that you really shouldn't be doing in C++, as it includes messing around with void*. It needs to be used here because of the interaction with the C API. If you can, use std::thread from C++11 or boost::thread if you're using an older compiler.
To answer your question : yes, it is perfectly fine to make a class object as a callable (as a "function") once you implement operator() for it. You already did that, but the problem is the extra code needed to implement the interface between C++ and the C API for Pthreads.
The main reason why you're getting the "processor cannot be used as a function" error here is because processor is a CommandProcessor* and, as such, needs a dereference. However, even doing (*processor)() wouldn't help you, because pthread_create is defined as follows :
int pthread_create(phread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
This means that the function to be executed must return void* and take a void*. The documentation also states that the parameter of start_routine has the value of arg originally given to the respective call to pthread_create.
However, you cannot pass a pointer to CommandProcessor::operator()() to pthread_create for a much more important reason : it is a member function. All non-static class member functions need to be called with an object so that they can refer to this inside their body.
The solution to your problem is to make a static function that will match the prototype required by pthread_create, and pass the pointer to a CommandProcessor as the arg of pthread_create. Have a look at this :
static void* processor_executor(void *arg)
{
CommandProcessor *processor = static_cast<CommandProcessor*>(arg);
(*processor)();
return NULL;
}
int main(int argc, char **argv)
{
/* ... */
for(int i=0; i < MAX_THREADS; i++)
{
pthread_create(&threads[i], NULL, processor_executor, static_cast<void*> (processor));
}
/* ... */
}
This way, operator() is executed inside the thread created by pthread_create, using the same CommandProcessor object as the one in main().
Keep in mind that accessing the same data from within many parallel threads will lead to data races. Use mutexes, semaphores, or condition variables to protect the data from parallel access.

Getting error when using pthread_create [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
pthread Function from a Class
I am fairly new to c++ and I am doing a project regarding TCP.
I need to create a thread so I googled and found this.
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html
I follow its syntax but encounter errors:
argument of type ‘void* (ns3::TcpSocketBase::)()’ does not match ‘void* ()(void)’
codes:
tcp-socket-base.h:
class TcpSocketBase : public TcpSocket
{
public:
...
void *threadfunction();
....
}
tcp-socket-base.cc:
void
*TcpSocketBase::threadfunction()
{
//do something
}
..//the thread was create and the function is called here
pthread_t t1;
int temp = pthread_create(&t1, NULL, ReceivedSpecialAck, NULL); //The error happens here
return;
...
Any help would be appreciated. Thanks!
EDIT:
I took the advise and make the threadfunction a non member function.
namespaceXXX{
void *threadfunction()
int result = pthread_create(&t1, NULL, threadfunction, NULL);
NS_LOG_LOGIC ("TcpSocketBase " << this << " Create Thread returned result: " << result );
void *threadfunction()
{
.....
}
}
But I got this error instead:
initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’ [-fpermissive]
If you'd like to continue using pthreads, a simple example is:
#include <cstdio>
#include <string>
#include <iostream>
#include <pthread.h>
void* print(void* data)
{
std::cout << *((std::string*)data) << "\n";
return NULL; // We could return data here if we wanted to
}
int main()
{
std::string message = "Hello, pthreads!";
pthread_t threadHandle;
pthread_create(&threadHandle, NULL, &print, &message);
// Wait for the thread to finish, then exit
pthread_join(threadHandle, NULL);
return 0;
}
A better alternative, if you're able to, is to use the new C++11 thread library. It's a simpler, RAII interface that uses templates so that you can pass any function to a thread, including class member functions (see this thread).
Then, the above exmaple simplifies to this:
#include <cstdio>
#include <string>
#include <iostream>
#include <thread>
void print(std::string message)
{
std::cout << message << "\n";
}
int main()
{
std::string message = "Hello, C++11 threads!";
std::thread t(&print, message);
t.join();
return 0;
}
Note how you can just pass data directly in - casts to and from void* are not needed.
You look to be passing a member function of a class to your pthread_create function. The thread function should be a non-member function that has the following signature
void *thread_function( void *ptr );
If you declare the function static it will compile.