Archive

Posts Tagged ‘variables’

Shared variables between child processes in C [fork()]

March 5, 2014 No comments

Another way of facing concurrency in the wonderful world of doing several task at the same time is using child processes with fork(). The main difference between fork and threads is that forked process are full process, they have their own memory for code, for data and stack, while threads share code and data, and have their own stack.

But, what about sharing variables in forked processes? If we try to make it as simpler as in thread examples, it’s not going to work, because as they are different processes, they are using different memory zones for their data. For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

int main()
{
  int child;
  int *number = malloc(sizeof(int));
  int i;

  *number = 10;

  child = fork();

  if (child==-1)
    {
      exit(1);
    }
  else if (child==0)
    {
      for (i=0; i<10; ++i)
    {
      usleep(100);
      printf ("CHILD -- Number: %d\n", *number);
      *number=i;
    }
      exit(0);
    }
  else
    {
      for (i=20; i<30; ++i)
    {
      usleep(100);
      printf ("MAIN -- Number: %d\n", *number);
      *number=i;
    }
    }
  wait(NULL);
  free(number);
}

In our ideal world, the MAIN process can see the values written by CHILD and vice versa, but the value the MAIN process can access is completely different than the value the CHILD can access, even using malloc before calling fork(). fork() copies the values of all variables before fork(), but the physical memory address is different.

To do that we have to work with shared memory, have to use mmap instead of malloc:

1
2
  int *number = mmap(NULL, sizeof(int), PROT_READ | PROT_WRITE,
               MAP_SHARED | MAP_ANONYMOUS, -1, 0);

And, like malloc() uses free() to free memory, with mmap we will use:

1
mmunmap(number, sizeof(int));

And, of course, when using threads we can have a race condition, we must use mutex here too to solve the problem.
Photo: Rudolf Vicek (Flickr) CC-by

Concurrency, POSIX threads and shared variables in C

January 14, 2014 No comments

A few days ago, we talked about building our first multi-thread programs using POSIX threads. But soon a need arises: share data between the main thread and the recently launched thread, at least to indicate what we want it to do.
So we can use the last argument of pthread_create(), this is a void pointer we can use for whatever we want and pass the variable type we want. For example an integer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *newtask(void *_number)
{
  int number = *(int*)_number;
  printf("The number I was asked for: %d\n", number);
  pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread;
   int rc;
   int i;
   int number = 99;

   printf ("Main process just started.\n");
   rc = pthread_create(&thread, NULL, newtask, &number);
   if (rc)
     {
       printf("ERROR in pthread_create(): %d\n", rc);
       exit(-1);
     }

   printf ("Main process about to finish.\n");
   /* Last thing that main() should do */
   pthread_exit(NULL);
}

Remember to compile using pthread:

$ gcc -o simplepass simplepass.c -lpthread

This way, the thread can read the value we’ve passed him, as we can see if we run this little program. Just after starting newtask() we extract the number from the void pointer to an integer variable. But working a bit on this code we can realize this variable can be bi-directional, in other words, we can write a value from the secondary thread, and the main thread can read it. (Instead of doing this, we can use global variables, but I don’t like it much):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

void *newtask(void *_number)
{
  int *number = _number;
  printf("The number I was asked for: %d\n", *number);
  *number = 10;
  pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread;
   int rc;
   int i;
   int number = 99;

   printf ("Main process just started.\n");
   rc = pthread_create(&thread, NULL, newtask, &number);
   if (rc)
     {
       printf("ERROR in pthread_create(): %d\n", rc);
       exit(-1);
     }

   usleep(100000);

   printf (" Before exiting. Number = %d\n", number);

   printf ("Main process about to finish.\n");
   /* Last thing that main() should do */
   pthread_exit(NULL);
}

Now, if we want to pass multiple arguments to the secondary thread, we can create a struct which stores all variables we want to use there:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

struct thread_vars_t
{
  int number;
  char string[50];
};

void *newtask(void *_number)
{
  struct thread_vars_t *vars = _number;

  printf("The number I was asked for: %d\n", vars->number);
  vars->number = 10;
  strcpy(vars->string, "Hello world from thread");
  pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread;
   int rc;
   int i;
   struct thread_vars_t *vars = malloc (sizeof(struct thread_vars_t));


   vars->number = 99;

   printf ("Main process just started.\n");
   rc = pthread_create(&thread, NULL, newtask, vars);
   if (rc)
     {
       printf("ERROR in pthread_create(): %d\n", rc);
       exit(-1);
     }

   usleep(100000);

   printf (" Before exiting. Number = %d\n", vars->number);
   printf (" Before exiting. String = %s\n", vars->string);

   printf ("Main process about to finish.\n");
   /* Last thing that main() should do */
   pthread_exit(NULL);
}

In older and slower computers, we may have to cary the value passed to usleep(), I’m just simulating a wait, it could be the time taken by additional computation. But using a sleep could be a problem, depending on the computer capabilities this value must change, or we could give a high value to make it compatible with more computers, but it could be a waste of time for modern computers. We can solve it many ways, but this first one will be a demo of what you shouldn’t do making an active wait:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>

struct thread_vars_t
{
  int ready;
  int number;
  char string[50];
};

void *newtask(void *_number)
{
  struct thread_vars_t *vars = _number;

  printf("The number I was asked for: %d\n", vars->number);
  vars->number = 10;
  strcpy(vars->string, "Hello world from thread");
  vars->ready = 1;
  pthread_exit(NULL);
}

int main (int argc, char *argv[])
{
   pthread_t thread;
   int rc;
   int i;
   struct thread_vars_t *vars = malloc (sizeof(struct thread_vars_t));

   vars->ready = 0;
   vars->number = 99;

   printf ("Main process just started.\n");
   rc = pthread_create(&thread, NULL, newtask, vars);
   if (rc)
     {
       printf("ERROR in pthread_create(): %d\n", rc);
       exit(-1);
     }

   //   usleep(100000);
   while (!vars->ready);
   printf (" Before exiting. Number = %d\n", vars->number);
   printf (" Before exiting. String = %s\n", vars->string);

   printf ("Main process about to finish.\n");
   /* Last thing that main() should do */
   pthread_exit(NULL);
}

In this case, we have a new variable (vars->ready), when it’s 1 it means the values are set by the secondary thread, so the main one can read them. The main thread, to wait for vars->ready is asking all the time for this value while it’s 0:

1
while (!vars->ready);

But it has a great disadvantage: the process is eating CPU while the condition is not met. We can see it clearer writing sleep(20) just before the secondary thread set ready to 1, and use a task manager to see how CPU use is going, our process will use a big percentage of CPU for nothing, just waiting. If we think about it and the secondary thread is doing any type of complex calculation, the main thread will be stealing CPU time obstructing the secondary one, making it slower, so we have to use another type of solution, like semaphores, signals, mutex, etc. But I’ll talk about them in another post.
Photo: OakleyOriginals (Flickr) CC-by

Call a variable whose name is contained by another one [BASH]

November 4, 2013 No comments

numbers

I’m sure this has happened to you. Imagine we have three variables (RED = “ff0000″ ; GREEN = “00ff00″ ; BLUE = “0000ff”) and a function which giving the name of the color, it gives us the code. Ok, we can do this many ways, but this is just an example. What I want is to tell get_color() function a name of a variable, and it will give me the value:

1
2
3
4
5
6
7
8
9
10
RED="ff0000"
GREEN="00ff00"
BLUE="0000ff"

function get_color()
{
   echo ${!1}
}

get_color BLUE

The key, as you may see is the ! sign before the name of the variable in braces. It can be a bit more clearer:

1
2
3
4
5
6
7
SEVILLE="Torre del Oro"
LONDON="Big Ben"
NEWYORK="Statue of Liberty"

CITY=SEVILLE

echo I really like to go to $CITY to see ${!CITY}

If I change the value of CITY, it will pick another monument from the list before.

Swapping variable values (examples in C)

October 10, 2013 No comments

So we want to make a variable named “a” have the value of a variable called “b” and vice versa. We can do it in several ways. (The examples may be silly but I will talk later about some good uses of it)

The first way is using a temporary variable so we (as original as we can), will call it tmp. We can do a program like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
  int a = 11;
  int b = 99;
  int tmp;

  printf ("Current a value: %d\n", a);
  printf ("Current b value: %d\n", b);
  printf ("\n\n"); // Some lines to make it clearer

  tmp = a; // so tmp=11; a=11; b=99;
  a = b;   // so tmp=11; a=99; b=99;
  b = tmp; // so tmp=11; a=99; b=11;

  printf ("New a value: %d\n", a);
  printf ("New b value: %d\n", b);

  return 0;
}

Compile it as you usually do with your IDE or in GCC with:

$ gcc -o swapvar swapvar.c

This type is swapping will be useful for any type of variable (int, float, char, structs, etc), but we must create a variable, that is, we will spend more memory (yeah, I know, memory is cheap nowadays, it would be a problem back in the 80′s, but not now).

We can create a function for this and the operation will be made by calling swap(a, b), just follow the following example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>

void swap(int *a, int *b)
{
  int tmp;
  tmp = *a;
  *a = *b;
  *b = tmp;
}

int main()
{
  int a = 11;
  int b = 99;
  int tmp;

  printf ("Current a value: %d\n", a);
  printf ("Current b value: %d\n", b);
  printf ("\n\n"); // Some lines to make it clearer

  swap(&a, &b);

  printf ("New a value: %d\n", a);
  printf ("New b value: %d\n", b);

  return 0;
}

Don’t forget the asterisks, so we are passing arguments to swap function by reference (in other words, with pointers), when calling the function we use “ampersand variable” (&variable), getting the memory address of this variable and passing it to the function. Inside the function we use asterisks to know the value stored in the address the pointer is pointing to. It would be much more easy in C++, because to pass a variable by reference in C++ we don’t have to fight with pointers. Like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

using namespace std;

void swap(int &a, int &b)
{
  int tmp;
  tmp = a;
  a = b;
  b = tmp;
}

int main()
{
  int a = 11;
  int b = 99;
  int tmp;

  cout << "Current a value: " << a << endl;
  cout << "Current b value: " << b << endl;
  cout << endl << endl;

  swap(a, b);

  cout << "New a value: " << a << endl;
  cout << "New b value: " << b << endl;

  return 0;
}

The other methods are only applicable when switching numeric variables (char, short, int, unsigned, long), because we will do mathematical operations with variables (float and double won’t always work due to precision problems. But I post them, for curious people, but in real life I’ve always used the first method.

Addition and subtraction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
  int a = 11;
  int b = 99;
  // No temporary var :)

  printf ("Current a value: %d\n", a);
  printf ("Current b value: %d\n", b);
  printf ("\n\n"); // Some lines to make it clearer

  a = a + b;  // a = 110 ; b = 99;
  b = a - b;  // a = 110 ; b = 11
  a = a - b;  // a = 99 ; b = 11

  printf ("New a value: %d\n", a);
  printf ("New b value: %d\n", b);

  return 0;
}

The other example is using the XOR operation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
  int a = 11;
  int b = 99;
  int tmp;

  printf ("Current a value: %d\n", a);
  printf ("Current b value: %d\n", b);
  printf ("\n\n"); // Some lines to make it clearer

  a ^= b;  // a = 104; b = 111          /* a = a xor b */
  b ^= a;  // a = 104; b = 11           /* b = b xor a */
  a ^= b;  // a = 99 ; b = 11           /* a = a xor b */

  printf ("New a value: %d\n", a);
  printf ("New b value: %d\n", b);

  return 0;
}

XOR is made bit by bit, it’s a binary opeator. R = A XOR B. R will result 1 only if one of the operators (A and B) is 1 (the other must be zero). So R will be 1 if A=1 and B=0 or A=0 and B=1. Making the operation in a numeric value means we will use the binary value of each number so:

11 = 00001011
99 = 01100011
————————
11^99 = 01101000 = 104

104 = 01101000
99 = 01100011
————————
104^99 = 00001011 = 11

104 = 01101000
11 = 00001011
——————–
104^11 = 01100011 = 99

That’s it, you can find this post in Spanish (not exactly the same content) in http://totaki.com/poesiabinaria/2009/06/intercambiar-valores/

Photo: I’ll never give up (Flickr) CC-by

Top