3

I'm trying to initialize arrays of mutexes and condition variables inside a function. The array is of type Cell which i deifined and each Cell contain mutex, condition variable and char. I'm getting the error on the 3 lines inside the for loop in intiail_circle:

expected expression before ‘{’ token.

I tried to initial the array also outside the function but it didn't help. any ideas what cause it?

the code:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 5    
#define num_of_cells  (2*(2*N - 2))


typedef struct Generator{
    pthread_t tid;
    int id;
}Genarator;

typedef struct Car{
    pthread_t carId;
    int location ,GenID,num_of_steps;
}Car;

typedef struct Cell{
    char val;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}Cell;

Cell circle[num_of_cells];
Cell generators_location[4];
struct Generator *generators[4];

int main(){
    initial_circle();
}

void initial_circle(){
    int i;
    for(i = 0; i < num_of_cells; i++){
        circle[i].mutex = PTHREAD_MUTEX_INITIALIZER;
        circle[i].cond = PTHREAD_COND_INITIALIZER;
        circle[i].val = ' ';
    }
}
Roy Ancri
  • 119
  • 2
  • 14

2 Answers2

4

The macros PTHREAD_MUTEX_INITIALIZER and PTHREAD_COND_INITIALIZER are initializers for a struct. They look like this:

#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
#define PTHREAD_MUTEX_INITIALIZER { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } }

This syntax is only valid in an initializer, not an assignment, which is why you're getting the error.

You can work around this by making a compound literal out of them:

    circle[i].mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    circle[i].cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;

Also, you're calling the function initial_circle before it is declared. You should move the definition of initial_circle further up in the file before main:

void initial_circle(){
    ...
}

int main(){
    initial_circle();
}
dbush
  • 205,898
  • 23
  • 218
  • 273
4

PTHREAD_MUTEX_INITIALIZER is an initializer! It expands to the form { /*stuff*/ }. You cannot use an initializer in assignment, an initializer has no type in C. Your problem can be reduced to this:

struct foo { char c; };
#define FOO_INIT { 'a' }

struct foo f =  FOO_INIT; // Okay
f = FOO_INIT; // Error

If you are compiling for or newer, you can work around the restriction by using a compound literal:

    circle[i].mutex = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
    circle[i].cond = (pthread_cond_t)PTHREAD_COND_INITIALIZER;

If c99 is not an option for you, use named objects:

    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
    circle[i].mutex = mutex;
    circle[i].cond = cond;
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • its work!!thnks. but one more question.. how can I use this for array? is it will initialized automatically? struct foo f = FOO_INIT; // Okay – Roy Ancri May 06 '19 at 12:27
  • @RoyAncri - You mean if the structure contains an array as a field? Will still work the same. But if have an array *instead* of a struct, it can't work. You can't assign to an array name. – StoryTeller - Unslander Monica May 06 '19 at 12:29