multithreading - Changing address contained by structure and its members using function (ANSI C) -
[edit]i added main code , of external functions used code. code quite long, in summary sends message device measuring parameters of water in container, , device responds corresponding value measured sensor. after code uses value modify level , temperature of water. prints current status of container , makes log.txt file.[/edit]
i want constructor object-oriented-like function in c, address of structure , members not being changed after malloc() them. saw answer changing address contained pointer using function , got idea of problem is, still can't solve it. below code doing constructor:
udp.c
#include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include "udp.h" #define buf_size 1000 #define header_size typedef struct{ int socket; char header[4]; float *send_value; char *message_buffer; }message; void build_message(message **msg, int socket, char header[], float *send_value){ *msg = (message *)malloc(sizeof(message)); (*msg)->socket = socket; strncpy((*msg)->header, header, 4); (*msg)->send_value = send_value; (*msg)->message_buffer = null; (*msg)->message_buffer = malloc(buf_size); //(**msg).message_buffer = (char *)(msg+sizeof(int) + sizeof(float *) + sizeof(char *)*3); } int prepara_socket_cliente(char *host, char *porta) { struct addrinfo hints; struct addrinfo *result, *rp; int sfd, s; /* obtain address(es) matching host/port */ memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = af_unspec; /* allow ipv4/ or ipv6 */ hints.ai_socktype = sock_dgram; /* datagram socket */ hints.ai_flags = 0; hints.ai_protocol = 0; /* protocol */ s = getaddrinfo(host, porta, &hints, &result); if (s != 0) { fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s)); exit(exit_failure); } /* getaddrinfo() returns list of address structures. try each address until connect(2). if socket(2) (or connect(2)) fails, (close socket and) try next address. */ for( rp = result; rp != null; rp = rp->ai_next) { sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sfd == -1) continue; if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) break; /* success */ close(sfd); } if (rp == null) { /* no address succeeded */ fprintf(stderr, "could not connect\n"); exit(exit_failure); } freeaddrinfo(result); /* no longer needed */ return sfd; } float receive_message(message *msg){ ssize_t nread; int len; //sprintf(msg->message_buffer, "%s0.0", msg->header); len = strlen(msg->message_buffer)+1; int rc; if (len + 1 > buf_size){ fprintf(stderr, "ignoring long message in argument\n"); exit(exit_failure); } if((rc = write(msg->socket, msg->message_buffer, len)) != len){ printf("%d, %d\n", len, rc); fprintf(stderr, "partial/failed write\n"); exit(exit_failure); } nread = read(msg->socket, msg->message_buffer, buf_size); if (nread == -1){ perror("read"); exit(exit_failure); } return atof(msg->message_buffer+3); } int send_message(message *msg){ ssize_t nread; int len; //sprintf(msg->message_buffer, "%s%.1f", msg->header, *msg->send_value); len = strlen(msg->message_buffer)+1; int rc; if (len + 1 > buf_size){ fprintf(stderr, "ignoring long message in argument\n"); exit(exit_failure); } if((rc = write(msg->socket, msg->message_buffer, len)) != len){ printf("%d, %d\n", len, rc); fprintf(stderr, "partial/failed write\n"); exit(exit_failure); } nread = read(msg->socket, msg->message_buffer, buf_size); if (nread == -1){ perror("read"); exit(exit_failure); } return 0; }
main.c
#include<pthread.h> #include<stdio.h> #include<errno.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h> #include<netdb.h> #include<unistd.h> #include<math.h> #include<time.h> #include<termios.h> #include"controller.h" #include"screen.h" #include"myio.h" #include"my_time.h" #include"data_structures.h" #include"udp.h" #define num_threads 5 #define max_param_size 20 #define max_buffer_size 1200 //variables typedef enum {idle, quit, change_level_ref, change_temp_ref} command_type; struct timespec t1; struct timespec t2; pthread_cond_t screen = pthread_cond_initializer; pthread_cond_t cmd = pthread_cond_initializer; pthread_cond_t barrier = pthread_cond_initializer; int count[2] = {0,0}; command_type command = idle; double_buffer* log_buffer; char* port = null; char* host = null;; int socket_cliente; real ta, ti, no; real t=0; real h=0; real q=0; real nf=0; real ni=0; real na=0; real href = 2.0; real tref = 25.0; pthread_mutex_t em_scan; pthread_mutex_t em; void init(){ port = (char *)malloc(sizeof(char)*max_param_size); host = (char *)malloc(sizeof(char)*max_param_size); log_buffer = build_double_buffer(); } //threads void *levelcontrol(void *threadid){ /********************************************************** *thread responsible controling water level *********************************************************/ controller* levelcontrol = null; levelcontrol = build_controller(); levelcontrol->kp = 10000.0; levelcontrol->ki = 0.0; levelcontrol->kd = 0.0; levelcontrol->error_thresh = 1.0; levelcontrol->step_time = 0.7; levelcontrol->max_actuator_value = 100.0; levelcontrol->min_actuator_value = 0.0; int intervalo = 90000000; message *message_h = null; build_message(&message_h, socket_cliente, "sh-", &h); sprintf(message_h->message_buffer, "%s0.0", message_h->header); message *message_nf = null; build_message(&message_nf, socket_cliente, "anf", &nf); message *message_ni = null; build_message(&message_ni, socket_cliente, "ani", &ni); loop_1: if(command != quit){ pthread_mutex_lock(&em); h = receive_message(message_h); levelcontrol->error = href - h; if(levelcontrol->error < 0.0){ levelcontrol->error = -levelcontrol->error; nf = pid_update(levelcontrol); ni = 0.0; }else{ ni = pid_update(levelcontrol); nf = 0.0; } sprintf(message_nf->message_buffer, "%s%f", message_nf->header, *message_nf->send_value); send_message(message_nf); sprintf(message_ni->message_buffer, "%s%f", message_ni->header, *message_ni->send_value); send_message(message_ni); count[1] = 1; if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier); next_timer(t1, intervalo); pthread_mutex_unlock(&em); goto loop_1; }else return null; } void *tempcontrol(void *threadid){ /********************************************************** * thread responsible controling temperature *********************************************************/ controller *tempcontrol = null; tempcontrol = build_controller(); tempcontrol->kp = 10000.0; tempcontrol->ki = 0.0; tempcontrol->kd = 0.0; tempcontrol->error_thresh = 20.0; tempcontrol->step_time = 0.7; tempcontrol->max_actuator_value = 10000.0; tempcontrol->min_actuator_value = 0.0; int intervalo = 70000000; message *message_t = null; build_message(&message_t, socket_cliente, "st-", &t); sprintf(message_t->message_buffer, "%s0.0", message_t->header); message *message_q = null; build_message(&message_q, socket_cliente, "aq-", &q); message *message_na = null; build_message(&message_na, socket_cliente, "ana", &na); char *log_string = null; log_string = (char *)malloc(sizeof(char)*max_buffer_size); // while(command != quit){ loop_2: if(command != quit){ pthread_mutex_lock(&em); t = receive_message(message_t); tempcontrol->error = tref - t; q = pid_update(tempcontrol); sprintf(message_q->message_buffer, "%s%f", message_q->header, *message_q->send_value); send_message(message_q); if(q == tempcontrol->max_actuator_value){ na = 10.0; }else if(q == tempcontrol->min_actuator_value){ na = 0.0; } sprintf(message_na->message_buffer, "%s%f", message_na->header, *message_na->send_value); send_message(message_na); count[0] = 1; if((count[0] == 1) & (count[1] == 1)) pthread_cond_signal(&barrier); pthread_mutex_unlock(&em); sprintf(log_string, "temperura: %f\n", t); setdoublebuffer(log_buffer, log_string); next_timer(t2, intervalo); goto loop_2; }else return null; // pthread_exit(null); } void *status(void *threadid){ /********************************************************** *thread responsible printing current status on *the screen , setting tref , href *********************************************************/ message *message_ta = null; build_message(&message_ta, socket_cliente, "sta", &ta); sprintf(message_ta->message_buffer, "%s0.0", message_ta->header); message *message_ti = null; build_message(&message_ti, socket_cliente, "sti", &ti); sprintf(message_ti->message_buffer, "%s0.0", message_ti->header); message *message_no = null; build_message(&message_no, socket_cliente, "sno", &no); sprintf(message_no->message_buffer, "%s0.0", message_no->header); pthread_mutex_lock(&em); while((count[0] != 1) | (count[1] != 1)) pthread_cond_wait(&barrier, &em); pthread_mutex_unlock(&em); //while(command != quit){ loop_3: switch(command){ case idle: pthread_mutex_lock(&em); clearscreen(); ta = receive_message(message_ta); ti = receive_message(message_ti); no = receive_message(message_no); printf("/********************************************************************************************************\n"); printf("*status\n"); printf("*reference temperature: %f\n", tref); printf("*reference water level: %f\n", href); printf("*current temperature: %f\n", t); printf("*current water level: %f\n", h); printf("*other sensor value => ni = %f, no = %f, na = %f, nf = %f, ta = %f, ti = %f\n", ni, no, na, nf, ta,ti); printf("*\n"); printf("*\n"); printf("*\n"); printf("*(q)uit, change (l)evel reference, change (t)emperature reference\n"); pthread_mutex_unlock(&em); sleep(1); break; case change_level_ref: pthread_mutex_lock(&em_scan); printf("insert new level reference\n"); scanf("%f", &href); pthread_cond_signal(&screen); while(command != idle){ pthread_cond_wait(&cmd, &em_scan); } pthread_mutex_unlock(&em_scan); break; case change_temp_ref: pthread_mutex_lock(&em_scan); printf("insert new temperature reference\n"); scanf("%f", &tref); pthread_cond_signal(&screen); while(command != idle){ pthread_cond_wait(&cmd, &em_scan); } pthread_mutex_unlock(&em_scan); case quit: fprintf(stderr, "get saiu\n"); return null; } goto loop_3; //return null; } void *getreferences(void *threadid){ /********************************************************** *thread responsible changing program mode *********************************************************/ char temp; //while(command != quit){ loop_4: temp = getch(); switch(temp){ case 'q': command = quit; printf("%c\n --------------------------------------------------------\n", temp); return null; case 'l': pthread_mutex_lock(&em_scan); command = change_level_ref; pthread_cond_wait(&screen, &em_scan); command = idle; pthread_cond_signal(&cmd); pthread_mutex_unlock(&em_scan); break; case 't': pthread_mutex_lock(&em_scan); command = change_temp_ref; pthread_cond_wait(&screen, &em_scan); command = idle; pthread_cond_signal(&cmd); pthread_mutex_unlock(&em_scan); } goto loop_4; } void *log(void *threadid){ char *receive_buffer = null; receive_buffer = (char *)malloc(sizeof(char)*max_buffer_size); //while(command != quit){ loop_5: if(command != quit){ get_buffer(receive_buffer, log_buffer); write_log(receive_buffer); goto loop_5; }else return null; } int main (int argc, char *argv[]){ init(); pthread_mutex_init(&em_scan, null); pthread_mutex_init(&em, null); init_nano_timer(t1); init_nano_timer(t2); clearscreen(); printf("enter port used in udp communication\n"); scanf("%s", port); strcpy(host, "localhost"); socket_cliente = prepara_socket_cliente(host, port); pthread_t threads[num_threads]; int rc; int t; void *threadname[num_threads]; threadname[0] = tempcontrol; threadname[1] = levelcontrol; threadname[2] = status; threadname[3] = getreferences; threadname[4] = log; for(t=0; t<num_threads; t++){ rc = pthread_create(&threads[t], null, threadname[t], (void *)t); if(rc){ printf("error; return code pthread_create() %d\n", rc); exit(1); } } for(t=0; t<num_threads; t++){ rc = pthread_join(threads[t], null); if(rc){ printf("error; return code pthread_create() %d\n", rc); exit(1); } } return 0; }
btw, using threads in these code, code thread-safe without mutexes?
as @sourav ghosh rightly commented you:
void build_message(message **msg, int socket, char header[], float *send_value) { *msg = malloc(sizeof(message)); (*msg)->socket = socket; strncpy((*msg)->header, header, 4); (*msg)->send_value = send_value; (*msg)->message_buffer = malloc(buf_size); }
change structure to:
typedef struct{ int socket; char header[4]; float *send_value; char *message_buffer; }message;
Comments
Post a Comment