1//------------------------------------------------------------------------------
2// Copyright (c) 2016 by Lukasz Janyst <lukasz@jany.st>
3//------------------------------------------------------------------------------
4// This file is part of thread-bites.
5//
6// thread-bites is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// thread-bites is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with thread-bites. If not, see <http://www.gnu.org/licenses/>.
18//------------------------------------------------------------------------------
19
20#include <tb.h>
21#include <string.h>
22
23tbthread_mutex_t mutex = TBTHREAD_MUTEX_INITIALIZER;
24tbthread_cond_t condvar = TBTHREAD_COND_INITIALIZER;
25int num = 0;
26
27//------------------------------------------------------------------------------
28// Thread function
29//------------------------------------------------------------------------------
30void *waiter_func(void *arg)
31{
32 tbthread_t self = tbthread_self();
33 tbprint("[thread 0x%llx] Starting a waiter\n", self);
34 for(int i = 0; i < 2; ++i) {
35 tbthread_mutex_lock(&mutex);
36 tbprint("[thread 0x%llx] Waiting for the condvar\n", self);
37 tbthread_cond_wait(&condvar, &mutex);
38 ++num;
39 tbsleep(1);
40 tbprint("[thread 0x%llx] Num = %d\n", self, num);
41 tbthread_mutex_unlock(&mutex);
42 tbsleep(1);
43 }
44 tbprint("[thread 0x%llx] Finishing a waiter\n", self);
45 return 0;
46}
47
48//------------------------------------------------------------------------------
49// Thread function
50//------------------------------------------------------------------------------
51void *poster_func(void *arg)
52{
53 tbthread_t self = tbthread_self();
54 tbprint("[thread 0x%llx] Starting the poster\n", self);
55 tbsleep(1);
56 tbthread_mutex_lock(&mutex);
57 for(int i = 0; i < 5; ++i) {
58 tbprint("[thread 0x%llx] Signal %d\n", self, i);
59 tbthread_cond_signal(&condvar);
60 }
61 tbthread_mutex_unlock(&mutex);
62 tbsleep(10);
63 tbthread_mutex_lock(&mutex);
64 tbprint("[thread 0x%llx] Broadcast\n", self);
65 tbthread_cond_broadcast(&condvar);
66 tbthread_mutex_unlock(&mutex);
67 tbprint("[thread 0x%llx] Finishing the poster\n", self);
68 return 0;
69}
70
71//------------------------------------------------------------------------------
72// Start the show
73//------------------------------------------------------------------------------
74int main(int argc, char **argv)
75{
76 tbthread_init();
77
78 tbthread_t thread[6];
79 void *(*thfunc[6])(void *);
80 tbthread_attr_t attr;
81 int st = 0;
82
83 for(int i = 0; i < 5; ++i)
84 thfunc[i] = waiter_func;
85 thfunc[5] = poster_func;
86
87 //----------------------------------------------------------------------------
88 // Spawn the threads
89 //----------------------------------------------------------------------------
90 tbthread_attr_init(&attr);
91 for(int i = 0; i < 6; ++i) {
92 st = tbthread_create(&thread[i], &attr, thfunc[i], 0);
93 if(st != 0) {
94 tbprint("Failed to spawn thread %d: %s\n", i, tbstrerror(-st));
95 goto exit;
96 }
97 }
98
99 tbprint("[thread main] Threads spawned successfully\n");
100
101 for(int i = 0; i < 6; ++i) {
102 st = tbthread_join(thread[i], 0);
103 if(st != 0) {
104 tbprint("Failed to join thread %d: %s\n", i, tbstrerror(-st));
105 goto exit;
106 }
107 }
108
109 tbprint("[thread main] Threads joined\n");
110
111exit:
112 tbthread_finit();
113 return st;
114};
115