Skip to content

Commit a995bbb

Browse files
author
Anton Yarkov
committed
Added some work with PThreads
1 parent 015c5b2 commit a995bbb

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

multithreading/05 - PThreads.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <pthread.h>
2+
3+
#include "Defs.h"
4+
5+
// Compilation:
6+
// gcc -std=gnu99 -pthread ErrorHandling.c LogF.c "05 - PThreads.c" -o pthreads
7+
8+
// Task:
9+
// Simple example of a counter working in 2 threads.
10+
11+
static long x = 0;
12+
13+
static void* thread_func(void* arg)
14+
{
15+
while (true)
16+
{
17+
printf("Thread 2, counter value %ld\n", ++x);
18+
sleep(1);
19+
}
20+
}
21+
22+
int main(void)
23+
{
24+
pthread_t tid;
25+
26+
ec_rv(pthread_create(&tid, NULL, thread_func, NULL))
27+
28+
while (x < 10)
29+
{
30+
printf("Thread 1, counter value %ld\n", ++x);
31+
sleep(2);
32+
}
33+
return EXIT_SUCCESS;
34+
35+
EC_CLEANUP_BGN
36+
return EXIT_FAILURE;
37+
EC_CLEANUP_END
38+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#include <pthread.h>
2+
3+
#include "Defs.h"
4+
5+
// Compilation:
6+
// gcc -std=gnu99 -pthread ErrorHandling.c LogF.c "06 - PThreads Joinable BAD.c" -o joinable_threads
7+
8+
// Task:
9+
// Simple example of an application working with 2 threads, where parent waits results from child.
10+
// Thread 2 stops calculation if common value already more than limit.
11+
12+
// WARNING! Code contains a problem marked with comment.
13+
14+
static long x = 0;
15+
16+
static void* thread_func(void* arg)
17+
{
18+
while (x < (long)arg)
19+
{
20+
printf("Thread 2, counter value %ld\n", ++x); // !!! WARNING!!! 2 Threads use the same variable. But increment operation is not atomic.
21+
sleep(1);
22+
}
23+
24+
return (void *)x;
25+
}
26+
27+
int main(void)
28+
{
29+
pthread_t tid;
30+
void *status;
31+
32+
assert(sizeof(long) <= sizeof(void *));
33+
ec_rv( pthread_create(&tid, NULL, thread_func, (void *)6) )
34+
35+
while (x < 10)
36+
{
37+
printf("Thread 1, counter value %ld\n", ++x); // !!! WARNING!!! 2 Threads use the same variable. But increment operation is not atomic.
38+
sleep(2);
39+
}
40+
41+
ec_rv( pthread_join(tid, &status) )
42+
printf("Return code of a Thread 2: %ld\n", (long)status);
43+
44+
return EXIT_SUCCESS;
45+
46+
EC_CLEANUP_BGN
47+
return EXIT_FAILURE;
48+
EC_CLEANUP_END
49+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <pthread.h>
2+
3+
#include "Defs.h"
4+
5+
// Compilation:
6+
// gcc -std=gnu99 -pthread ErrorHandling.c LogF.c "07 - PThreads Joinable with Sync.c" -o joinable_threads_synced
7+
8+
// Task:
9+
// Simple example of an application working with 2 threads, where parent waits results from child.
10+
// Thread 2 stops calculation if common value already more than limit.
11+
12+
// Access to variable is controlled with mutex.
13+
14+
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
15+
static long x = 0;
16+
17+
static void* thread_func(void* arg)
18+
{
19+
bool done;
20+
21+
while (true)
22+
{
23+
ec_rv( pthread_mutex_lock(&mtx) )
24+
done = x <= (long)arg;
25+
ec_rv( pthread_mutex_unlock(&mtx) )
26+
if (done)
27+
break;
28+
ec_rv( pthread_mutex_lock(&mtx) )
29+
printf("Thread 2, counter value %ld\n", ++x);
30+
ec_rv( pthread_mutex_unlock(&mtx) )
31+
sleep(1);
32+
}
33+
34+
return (void *)x;
35+
36+
EC_CLEANUP_BGN
37+
EC_FLUSH("thread_func")
38+
return NULL;
39+
EC_CLEANUP_END
40+
}
41+
42+
int main(void)
43+
{
44+
pthread_t tid;
45+
void *status;
46+
bool done;
47+
48+
assert(sizeof(long) <= sizeof(void *));
49+
ec_rv( pthread_create(&tid, NULL, thread_func, (void *)6) )
50+
51+
while (true)
52+
{
53+
ec_rv( pthread_mutex_lock(&mtx) )
54+
done = x >= 10;
55+
ec_rv( pthread_mutex_unlock(&mtx) )
56+
if (done)
57+
break;
58+
ec_rv( pthread_mutex_lock(&mtx) )
59+
printf("Thread 1, counter value %ld\n", ++x);
60+
ec_rv( pthread_mutex_unlock(&mtx) )
61+
sleep(2);
62+
}
63+
64+
ec_rv( pthread_join(tid, &status) )
65+
printf("Return code of a Thread 2: %ld\n", (long)status);
66+
67+
return EXIT_SUCCESS;
68+
69+
EC_CLEANUP_BGN
70+
return EXIT_FAILURE;
71+
EC_CLEANUP_END
72+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <pthread.h>
2+
3+
#include "Defs.h"
4+
5+
// Compilation:
6+
// gcc -std=gnu99 -pthread ErrorHandling.c LogF.c "08 - PThreads Joinable with Sync improved.c" -o joinable_threads_synced1
7+
8+
// Task:
9+
// Simple example of an application working with 2 threads, where parent waits results from child.
10+
// Thread 2 stops calculation if common value already more than limit.
11+
12+
// Access to variable is controlled with mutex, but located in the separate function.
13+
14+
static long get_and_incr_x(long incr)
15+
{
16+
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; // Must be static, because initialization function maybe not thread-safe.
17+
// And C++ may even use lazy initialization for mutex.
18+
static long x = 0;
19+
20+
// rtn and incr variables are on stack - i.e. local
21+
long rtn;
22+
23+
ec_rv( pthread_mutex_lock(&mtx) )
24+
rtn = x += incr; // Static variable - i.e. global. Needs to be protected.
25+
ec_rv( pthread_mutex_unlock(&mtx) )
26+
27+
return rtn;
28+
29+
EC_CLEANUP_BGN
30+
exit(EXIT_FAILURE);
31+
EC_CLEANUP_END
32+
}
33+
34+
static void* thread_func(void* arg)
35+
{
36+
long val = 0;
37+
while (val < (long)arg)
38+
{
39+
val = get_and_incr_x(1);
40+
printf("Thread 2, counter value %ld\n", val);
41+
sleep(1);
42+
}
43+
44+
return (void *)val;
45+
}
46+
47+
int main(void)
48+
{
49+
pthread_t tid;
50+
void *status;
51+
bool done;
52+
53+
assert(sizeof(long) <= sizeof(void *));
54+
ec_rv( pthread_create(&tid, NULL, thread_func, (void *)6) )
55+
56+
long val = 0;
57+
while (val < 10)
58+
{
59+
val = get_and_incr_x(1);
60+
printf("Thread 1, counter value %ld\n", val);
61+
sleep(2);
62+
}
63+
64+
ec_rv( pthread_join(tid, &status) )
65+
printf("Return code of a Thread 2: %ld\n", (long)status);
66+
67+
return EXIT_SUCCESS;
68+
69+
EC_CLEANUP_BGN
70+
return EXIT_FAILURE;
71+
EC_CLEANUP_END
72+
}

0 commit comments

Comments
 (0)