Passing 2 structures as parameters to pthread in C - c

Can I pass two structures as parameters to a pthread in a C program. I need to do something like this:
void *funtion1(void *pass_arg, void *pass_arg1)
{
struct thread_arg *con = pass_arg;
struct thread_arg1 *con = pass_arg1;
//necessary code
}
int main()
{
pthread_t threaad;
//necessary code
while(1)
{
th1 = pthread_create(&threaad, NULL, function1, (void *)&pass_arg, (void*)&pass_arg);
//necessary codes
}
pthread_exit(NULL);
return 1;
}
I mean is there any way I can pass two structures into the same function while using pthread? Operating Platform: Linux.

Not directly, because the functions in libpthread accept only one user data argument. But that should be enough, shouldn't it?
struct user_struct {
void *p1, *p2;
} arg = { &arg1, &arg2 };
pthread_create(&tid, NULL, threadfunc, &arg);
Also, don't cast pointers to void *, it's superfluous, dangerous and decreases readability.

Define a new struct type which contains the two original types as members. Call it something meaningful like thread_args.

I solved the problem by nesting the two structures into a single structure like this:
struct s1
{
//variables
};
struct s2
{
//variables
}
struct s3
{
struct s1 ss1;
struct s2 ss2;
}
void *funtion1(void *pass_arg)
{
struct s3 *con = pass_arg;
//necessary code
}
int main()
{
//code
th1 = pthread_create(&thread, NULL, function1, (void *)&pass_arg);
}

Related

How to pass multiples arguments to thread in c? [Segmentation fault]

I have tried to follow the procedures of several answers/tuturials and I'm still getting segmentation fault on passing multiple arguments to a thread? What am I doing wrong?
struct:
struct client_struct {
int socketId;
char *message;
};
process function:
// Handle socket session
void *process(void *client)
{
client_struct *tmpClient = (client_struct*)client;
char sendline[BUFFSIZE], recvline[BUFFSIZE];
printf("can't reach this: %i\n", tmpClient->socketId);
strncpy(sendline, tmpClient->message, sizeof(sendline)-1);
sendline[sizeof(sendline)-1] = '\0';
}
called from main:
int sendMessage(const char *message, int sock)
{
int result;
pthread_t process_thread;
struct client_struct * client;
client->socketId = sock;
strcpy(client->message, message);
printf("segmentation fault here: %s\n", client->message);
pthread_create(&process_thread, NULL, process, client);
pthread_detach(process_thread);
}
Classic problem with undefined behavior when pointer is not initialized.
struct client_struct * client;
client = malloc(sizeof(*client)); //Allocate memory for client
client->... = ...; //DO you job
By doing struct client_struct * client; you are only declaring variable which will (probably at some point) point to data of type struct client_struct. Since you don't have your data yet, dereferencing non-initialized pointer leads to undefined behavior.
By using malloc, you are setting up valid data for your pointer.
A simple proxyargs struct can be used also:
struct Args
{ int a; float f; char msg[10]; };
...
static void* callback(void* userData)
{
Args* a = (Args*) userData;
/* use args here */
}
...
Args mArgs = {10, 2.0, "message"};
pthread_create(&thread,NULL, callback, (Args*)&mArgs);
enter code here

Create pthread with the function of multiple arguments

If I am going to create a pthread for the following function.
Assume everything is properly delared.
pthread_create(&threadId, &attr, (void * (*)(void*))function, //what should be the arguments for here??);
int a = 0;
int b = 1;
//c and d are global variables.
void function(int a, int b){
c = a;
d = b;
}
This does not work. function() has to take exactly one argument. That's why you have to do this:
(void * ()(void))
You're telling your compiler "no, seriously, this function only takes one argument", which of course it doesn't.
What you have to do instead is pass a single argument (say a pointer to a struct) which gets you the information you need.
Edit: See here for an example: number of arguments for a function in pthread
The pthread thread function always takes one void * argument and returns a void * value. If you want to pass two arguments, you must wrap them in a struct - for example:
struct thread_args {
int a;
int b;
};
void *function(void *);
struct thread_args *args = malloc(sizeof *args);
if (args != NULL)
{
args->a = 0;
args->b = 1;
pthread_create(&threadId, &attr, &function, args);
}
and for the thread function itself:
void *function(void *argp)
{
struct thread_args *args = argp;
int c = args->a;
int d = args->b;
free(args);
/* ... */
You don't need to use malloc() and free(), but you must somehow ensure that the original thread doesn't deallocate or re-use the thread arguments struct until the called thread has finished with it.

C: Manipulate a structure declaired in the main from a created thread without the use of global variables

I'm trying to understand the use of threads in an application (I'm aware what I'm doing may be stupid in some sense) and I'm trying to understand how to manipulate variables declared in a structure in main from a created thread. So far i have:
typedef struct Chi_Server {
int thread_status;
int active_connections;
pthread_t thread_id;
pthread_attr_t thread_attribute;
struct thread_info *tinfo;
} CHI_SERVER;
int main(void) {
CHI_SERVER *chi_server;
chi_server_start_server(chi_server);
if (pthread_create(&chi_server->thread_id, (void *) &chi_server->thread_attribute, &chi_server_runtime, &chi_server)) {
perror("Creating main thread");
}
initscr();
noecho();
cbreak();
nodelay(stdscr, TRUE);
keypad(stdscr, TRUE);
curs_set(0);
do {
chi_server_time_alive(chi_server);
chi_server_display(chi_server);
} while (getch() != 113);
nocbreak();
endwin();
chi_server_stop_server(chi_server);
return 0;
}
void *chi_server_runtime(void *chi_server) {
chi_server->server_stats.active_connections = 1;
}
I just made the = 1 so I could see if the structure variables could be manipulated in the main. So far I am completely stumped. Does anyone have an idea how to manipulate the structure declared in main?
You seem to be confused about references when calling pthread_create; your last argument "&server" probably should just be server.
You cannot dereference a pointer to void as you are doing in server_runtime.
You should assign a struct Server pointer to the void pointer and use that.
Try this compiling with gcc -Wall thread.c -o thread -lpthread
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct Server {
pthread_attr_t thread_attribute;
pthread_t thread_id;
int active_connections;
};
void * server_runtime(void *);
/* Error checking omitted for clarity. */
int main()
{
struct Server *server;
void *result;
server = malloc(sizeof(struct Server));
pthread_attr_init(&server->thread_attribute);
pthread_create(&server->thread_id, &server->thread_attribute, server_runtime, server);
pthread_attr_destroy(&server->thread_attribute);
pthread_join(server->thread_id, &result);
printf("%d\n", server->active_connections);
free(server);
return 0;
}
void * server_runtime(void *p)
{
struct Server *server = p;
server->active_connections = 1;
return NULL;
}
In void *server_runtime(void *server).
You have to tell what kind of type *server is.
I havent seen your declaration of server, but i suppose it looks something like this
int main()
{
struct yourstruct server;
if (pthread_create(&server->thread_id, (void *) &server->thread_attribute,
&server_runtime, &server))
{
perror("Creating main thread");
}
}
void *server_runtime(void *_server)
{
struct yourstruct *server = _server;
server->active_connections = 1;
}
Probably missed something as usual.
Good luck.

The argument of pthread function can be another function?

I know how to pass a function as an argument for another function. But I don't know if the argument of a function passed to pthread can be another function. Is this even possible?
Here is sample code that compiles OK, but doesn't work:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_t idThread;
void aFunction(){
while(1){
fprintf(stderr,"I've been called!\n");
usleep(1000000);
}
}
void * threadFunction(void *argFunc){
// Do here some stuff;
// ...
// Now call the function passed as argument
void (*func)() = argFunc;
}
int thread_creator(void(*f)()){
// I want to use as argument for threadFunction the f function
pthread_create(&idThread, NULL, threadFUnction, (void *)f);
}
int main(){
thread_creator(aFunction);
while(1);
return 0;
}
It can be a function pointer, if you're willing to bend rules a little. Strictly speaking a void * isn't guaranteed to be able to hold a function pointer. Something like this (untested):
void some_fun()
{
/* ... */
}
void thread_fun(void *arg)
{
void (*fun)() = arg;
}
pthread_create(...., (void *) some_fun);
EDIT
In your example, you also need to call the function, via the function pointer. Something like:
void (*func)() = argFunc;
funct(); /* <-- */
Stricly speaking, it is not possible. According to the standard, a pointer to void may just be converted to or from a pointer to an object type. On some architectures, function adresses are larger than object adresses.
C11, § 6.3.2.3 Pointers
A pointer to void may be converted to or from a pointer to any object
type. A pointer to any object type may be converted to a pointer to
void and back again; the result shall compare equal to the original
pointer.
Otherwise, it is a common extension.
C11, § J.5.7 Function pointer casts
A pointer to an object or to void may be cast to a pointer to a
function, allowing data to be invoked as a function (6.5.4).
In your example, you don't call func.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_t idThread;
void aFunction(void)
{
while (1) {
fprintf(stderr, "I've been called!\n");
usleep(1000000);
}
}
void *threadFunction(void *argFunc)
{
void (*func)(void) = argFunc;
func(); /* HERE */
}
int thread_creator(void (*f)(void))
{
pthread_create(&idThread, NULL, threadFUnction, (void *) f);
}
int main(void)
{
thread_creator(aFunction);
while (1);
return 0;
}
To add to the answers already given:
Conceptually, function pointers can be passed around just like any other type of pointer, but - as has been pointed out - a void * is not guaranteed to be large enough to hold a function pointer, only a data pointer.
A workaround for something like the pthread_create callback function is to wrap your desired function pointer in a structure that you use as the user data:
struct threadArg
{
void (*callback)(void);
};
// ...
struct threadArg *threadArg = malloc(sizeof(threadArg));
threadArg->callback = myFunction;
pthread_create(&idThread, NULL, threadFunction, (void *) threadArg);
There is no need for dubious casts involving function pointers. The argument to the thread can be a pointer to a struct which can contain anything.
#include <pthread.h>
struct arg {
void (*func)(void);
int other_stuff;
};
void function(void)
{
}
void *thread_function(void *arg)
{
struct arg *a1 = arg;
a1->func();
return NULL;
}
int main(void)
{
pthread_t tid;
struct arg arg = {.func = function};
pthread_create(&tid, NULL, thread_function, &arg);
.
.
.
}

c passing several arguments to threads

when i create a thread, i want to pass several arguments.
So i define in a header file the following:
struct data{
char *palabra;
char *directorio;
FILE *fd;
DIR *diro;
struct dirent *strdir;
};
In a .c file i do the following
if (pthread_create ( &thread_id[i], NULL, &hilos_hijos, ??? ) != 0){
perror("Error al crear el hilo. \n");
exit(EXIT_FAILURE);
}
How do i pass all this arguments to the threads. I though about:
1) first use malloc to allocate memory for this structure and then give each parameter a value:
struct data *info
info = malloc(sizeof(struct data));
info->palabra = ...;
2) define
struct data info
info.palabra = ... ;
info.directorio = ...;
and then, how do i access these parameters in the thread
void thread_function ( void *arguments){
???
}
thanks in advance
Here is a working (and relatively small) example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
/*
* To compile:
* cc thread.c -o thread-test -lpthread
*/
struct info {
char first_name[64];
char last_name[64];
};
void *thread_worker(void *data)
{
int i;
struct info *info = data;
for (i = 0; i < 100; i++) {
printf("Hello, %s %s!\n", info->first_name, info->last_name);
}
}
int main(int argc, char **argv)
{
pthread_t thread_id;
struct info *info = malloc(sizeof(struct info));
strcpy(info->first_name, "Sean");
strcpy(info->last_name, "Bright");
if (pthread_create(&thread_id, NULL, thread_worker, info)) {
fprintf(stderr, "No threads for you.\n");
return 1;
}
pthread_join(thread_id, NULL);
return 0;
}
Do not use option #2. The data structure could be overwritten (explicitly, for instance using the same structure to start another thread, or implicitly, for instance having it overwritten on the stack). Use option #1.
To get at your data, at the start of your thread, do
struct data *info = (struct data*)arguments;
Then access info as normal. Make sure to free it when the thread is done (or, as I prefer, have the caller free it after joining with the thread).
Create a pointer to a struct like you do in the first case above:
//create a pointer to a struct of type data and allocate memory to it
struct data *info
info = malloc(sizeof(struct data));
//set its fields
info->palabra = ...;
info->directoro = ...;
//call pthread_create casting the struct to a `void *`
pthread_create ( &thread_id[i], NULL, &hilos_hijos, (void *)data);
1) you need to use malloc and not define like below
struct data *info;
info = (struct data *)malloc(sizeof(struct data));
and pass the pointer of the structure in ptherad call as below
pthread_create ( &thread_id[i], NULL, &thread_fn, (void *)info );
2) you can access them in thread function as below
void thread_function ( void *arguments){
struct data *info = (struct data *)arguments;
info->....
}

Resources