I am trying out multithreading of inorder traversal of binary trees. I am getting errors due to pthread_create.
#include <iostream>
#include <pthread.h>
#include <list>
using namespace std;
static pthread_t threads[9];
static int count=0;
struct node
{
int value=0;
node *left=NULL;
node *right=NULL;
};
list<int> inordertraversal(node* n)
{
list<int> l1,l2;
if(n->left!=NULL)
list<int> l1=pthread_create(&threads[count++],NULL,inordertraversal,n->left);
if(n->right!=NULL)
list<int> l2=pthread_create(&threads[count++],NULL,inordertraversal,n->right);
list<int> l;
l.insert(l.begin(),l1.begin(),l1.end());
l.push_back(n->value);
l.insert(l.end()--,l2.begin(),l2.end());
return l;
}
struct node* newNode(int data)
{
node* node;
node->value=data;
node->left=NULL;
node->right=NULL;
return node;
}
int main()
{
struct node *root=newNode(7);
root->left=newNode(9);
root->right=newNode(5);
root->left->left=newNode(13);
root->left->right=newNode(17);
root->right->left=newNode(56);
root->right->right=newNode(21);
root->left->left->left=newNode(45);
root->right->left->right=newNode(45);
root->left->left->right=newNode(67);
list<int> l=inordertraversal(root);
for(list<int>::iterator it=l.begin();it!=l.end();it++)
{
cout<<*it<<" ";
}
}
I would like to return list elements from the function passed on to the thread using pthread_create. The error is as follows:-
/usr/include/pthread.h|244|error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’ [-fpermissive]|
/home/dinu94/dummyspace/interview_prep/ThreadedBinaryTree/main.cpp|25|error: conversion from ‘int’ to non-scalar type ‘std::list’ requested|
/home/dinu94/dummyspace/interview_prep/ThreadedBinaryTree/main.cpp|28|error: invalid conversion from ‘std::list ()(node)’ to ‘void* ()(void)’ [-fpermissive]|
/usr/include/pthread.h|244|error: initializing argument 3 of ‘int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)’ [-fpermissive]|
/home/dinu94/dummyspace/interview_prep/ThreadedBinaryTree/main.cpp|28|error: conversion from ‘int’ to non-scalar type ‘std::list’ requested
I am not sure how to proceed.
edit: what are the alternative ways of returning value if pthread_create is the wrong way to do?
Thanks
A pthread thread function has to conform to function definition specified by library:
int pthread_create(pthread_t*, const pthread_attr_t*, void* ()(void), void*)
so, your function list<int> inordertraversal(node* n) does not conform to void* ()(void)
you will have to change your function signature to a function which conforms to above signature and then call that recursively.
void* inorder(void)
{
pthread_create(&threads[count++],NULL,wrapper,(void *)n->left);
}
Have list<int> l; as a class member, so that you dont need to pass it around with every function call.
You're misinterpreting what pthread_create does. It just creates the thread and returns the status of the thread creation (did it work or fail). It doesn't handle at all what the function running in the thread returns. In fact the thread function probably shouldn't be returning the result at all. It should probably be updating some common variable accessible to all threads (at which point mutexes or some other mutual exclusion mechanism are going to be needed).
pthread_create needs a function pointer which should have type void* ()(void*).
Your function has return type list .
Related
I am trying to include a structure in a library function in C++.
The structure goes like this:
struct NET_IN_OPERATE_FACERECONGNITIONDB{
DWORD dwSize;
EM_OPERATE_FACERECONGNITIONDB_TYPE emOperateType;
FACERECOGNITION_PERSON_INFO stPersonInfo;
char *pBuffer;
int nBufferLen;
}; `
And the function in which it is included goes like this:
BOOL CLIENT_OperateFaceRecognitionDB(
LLONG lLoginID,
const NET_IN_OPERATE_FACERECONGNITIONDB *pstInParam,
NET_OUT_OPERATE_FACERECONGNITIONDB *pstOutParam,
int nWaitTime = 1000,
);
I'm defining the structure to a pointer by writing the following lines:
const struct NET_OUT_OPERATE_FACERECONGNITIONDB{
DWORD dwSize = sizeof(NET_IN_OPERATE_FACERECONGNITIONDB);
EM_OPERATE_FACERECONGNITIONDB_TYPE emOperateType = NET_FACERECONGNITIONDB_ADD;
FACERECOGNITION_PERSON_INFO FACERECOGNITION_PERSON_INFO1;
char *pBuffer = '\0';
int nBufferLen = 10;
} *pstInParam;
but when I call that structure into the function using this line:
CLIENT_OperateFaceRecognitionDB(m_LoginID, pstInParam, pstOutParam, 1000);
I am getting an error saying
Argument of type “const NET_IN_OPERATE_FACERECONGNITIONDB *” is incompatible with parameter of type “const NET_IN_OPERATE_FACERECONGNITIONDB *”
This is very unusual, because both the argument and the parameter are of the same type. What mistake have I done?
This is very unusual, because both the argument and the parameter are of the same type.
They are not of the same type (which the error message tells you, though it is not very helpful in doing so).
What's going on here is that your declaration of pstInParam is in fact defining an anonymous struct, and then introducing a variable that is a pointer to this anonymous struct.
This is more readily seen in a reduced example, which yields a more helpful error on recent GCC versions:
struct some_struct {
int member;
};
bool some_function(const some_struct*) {
return false;
}
int main()
{
const struct some_struct {
int member = 0;
} *param;
some_function(param);
}
prog.cc: In function 'int main()':
prog.cc:15:22: error: cannot convert 'const main()::some_struct*' to 'const some_struct*' for argument '1' to 'bool some_function(const some_struct*)'
some_function(param)
What you (probably, depending on the ownership semantics of CLIENT_OperateFaceRecognitionDB) want to do is either to declare a some_struct and pass its address to the function:
int main()
{
const some_struct param{0};
some_function(¶m);
}
...or to allocate it on the free store:
int main()
{
const some_struct* param = new some_struct{0};
some_function(param);
delete param;
}
In the latter case, please consider using smart pointers if possible.
Okay so i'm looking at the documentation for pthread_create and I just don't understand at all how to do what I want to do.
I want to call pthread_create which will obv pass in a struct of pthread_t. But the function I pass to it takes in a pointer to a of MyNode*. How would I pass the function as a parameter and pass it "this" as a parameter to that function.
//MyNode field and method in class file
pthread_t myTrd;
static void compute(MyNode* node);
////////////////////////////////////////////////////////////
//Actual code in header file below
static void MyNode::compute(*MyNode node){ //L61
//code
}
void MyNode::run(){ //run function in header file
pthread_create(&(this->thread),NULL,MyNode::compute, this);
}
outcome:
myNode.cpp:61: error: 'static' may not be used when defining (as opposed to declaring) a static data member
myNode.cpp:61: error: 'int MyProjectGraph::MyNode::compute' is not a static member of 'class MyProjectGraph::MyNode'
myNode.cpp:61: error: expected primary-expression before 'node'
myNode.cpp:61: error: expected ',' or ';' before '{' token
myNode.cpp:134: error: expected `}' at end of input
The function passed to pthread_create() should match the prototype:
void *function(void *arg);
If your function does not match that, you have to use brute force and ignorance (and a cast) to make the function pointer acceptable — and then hope that the alternative interface doesn't break anything.
It is far better to make your function match the specification:
void *function(void *arg)
{
MyNode *mnp = (MyNode *)arg;
…
return 0;
}
The return can return some more meaningful value if you have one available, but returning a null (you could probably write nullptr given that you're mainly using C++).
Note that pthread_create() is usually a C function itself and expects C function semantics in the function pointer it is passed.
Having a thread per object isn't really a good way to go. I presume that
since you are calling your object a node, you have a bunch of them
and want to do something to them on a thread.
I typically do the following, which is a classic idiom:
class Worker
{
struct ThreadStr
{
Worker * worker;
// put parameters here
MyNode * node;
};
public:
static void *StaticHandler(void *pvoid)
{
ThreadStr * data = (ThreadStr*)pvoid;
data->worker->Compute(data->node);
delete data;
return NULL;
}
void Compute(MyNode *node)
{
// whatever you want to compute on a node.
}
// start a thread to execute Worker::Compute(MyNode*)
void Run(MyNode *node)
{
ThreadStr * data = new ThreadStr();
data->worker = this;
data->node = node;
pthread_t threadId;
pthread_create(&threadId, NULL, Worker::StaticHandler, data);
}
};
I have the following encapsulation for my pthread_t threads:
#include <pthread.h>
class Thread
{
public:
void run(const int);
static void *run_helper(void *);
bool startThread(int);
void joinThread();
pthread_t th;
};
Where run is my thread routine, and run_helper is the following:
void *Thread::run_helper(int num)
{
return (Thread *)this->run(num);
}
I start my threads like such:
bool Thread::startThread(intptr_t arg)
{
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
}
But when I compile, I get the following errors:
error: lvalue required as unary ‘&’ operand
return (pthread_create(&this->th, NULL, &run_helper(arg), (void *)(intptr_t)arg));
error: ‘this’ is unavailable for static member functions
return (Thread *)this->run(num);
And despite trying, I can't seem to make this encapsulation work.
I think your issue might specifically be &this->th. & has higher precedence than ->. Perhaps try &(this->th).
For the first error, you need to cast the third argument into (void*(*)(void*)) and remove & (maybe the casting isn't neccessary).
pthread_create(&this->th, NULL, (void*(*)(void*))run_helper(arg), (void *)(intptr_t)arg);
The second error, you are trying to use pointer to this in a static function, but the function isn't called on any object, therefore you can't use this in a function like that. The solution is to cast arg into Thread* and then call the non-static run function.
There is a class that contains some data and it sorts them at some point of time. I use qsort() and I'd like to keep the comparing function within the class as a method. The question is how to pass a method to qsort() so that the compiler (g++) don't throw any warnings?
Attempt 1:
int Data::compare_records(void * rec_1, void * rec_2){
// [...]
}
void Data::sort(){
qsort(records, count, sizeof(*records), &Data::compare_records);
}
This way generates an error:
error: cannot convert ‘int (Data::*)(const void*, const void*)’ to ‘int (*)(const void*, const void*)’ for argument ‘4’ to ‘void qsort(void*, size_t, size_t, int (*)(const void*, const void*))’
Attempt 2 :
void Data::sort(){
qsort(
records, count, sizeof(*records),
(int (*)(const void*, const void*)) &Data::compare_records
);
}
This way generates a warning:
warning: converting from ‘int (Data::*)(const void*, const void*)’ to ‘int (*)(const void*, const void*)’
How to do it the right way then?
If you must use qsort and not std::sort (recommended), declaring the member method as static should be enough.
You pass the function as &Data::compare_records, but you should pass it as Data::compare_records and also make it static
Don't use qsort in C++. Use std::sort and boost/std::bind. Member function-pointer cannot been converted to function-pointer. Your method should be static, or it should be free function.
see Is the type of “pointer-to-member-function” different from “pointer-to-function”? for an explanation.
This code may also help as a hint, for std::sort despite the fact I Use Qt's qSort()
Functors can be very cool.
struct randomWSort
{
SatoshiGame* This;
randomWSort(SatoshiGame* g){This=g;}
bool operator()(QString& a, QString& b)
{
return This->randomWSort(a,b);
}
};
bool SatoshiGame::randomWSort(QString& a, QString& b)
{
return rand->rnd() %2;
}
QString SatoshiGame::getRandomString(QStringList words)
{
qSort(words.begin(), words.end(), ::randomWSort(this) );
return words.at(0);
}
I have the following code:
#include<iostream>
using namespace std;
typedef void (*HandlerFunc)(int, int);
HandlerFunc mr;
HandlerFunc mm()
{
return mr;
}
void sample(int a, int b, HandlerFunc func)
{
}
void main()
{
sample(1, 2, mm);
}
Here I'm trying to pass a function of type HandlerFunc to another function, but I am getting an error:
Error :*: cannot convert parameter 3 from 'void (__cdecl *(void))(int,int)' to 'void (__cdecl *)(int,int)'
If I type cast as sample(1, 2, (HandlerFunc)mm); everything works fine.
Can anyone tell what is the way to solve the error issue?
HandlerFunc mm()
{...}
should be:
void mm(int, int)
{...}
Your function sample() takes a pointer to function(you typedefd as HandlerFunc) as last argument.
The address of the function you pass as this argument must match the type of the function to which it is a pointer.
No, no, you've confused the types. mm is a function that returns a function pointer of the appropriate type. However, mm itself is not of the appropriate type - it doesn't accept any parameters.
You should pass mr in main, or pass mm() (that is - call mm and pass the return value)
The code in main should be:
sample(1,2,mm());
as mm returns a HandlerFunc, it isn't one itself.
HandlerFunc mm()
{
return mr;
}
This means nm is function which will not receive any agruments(void), and it will reutrn a pointer to function of type void (*)(int, int)
so that only you are getting that error.