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
23//------------------------------------------------------------------------------
24//
25//------------------------------------------------------------------------------
26void cleanup(void *arg)
27{
28 tbprint("[thread 0x%llx] Canceled\n", arg);
29}
30
31//------------------------------------------------------------------------------
32// The once initializer
33//------------------------------------------------------------------------------
34tbthread_t once_thread;
35int once_one = 0;
36void once_func()
37{
38 tbthread_t self = tbthread_self();
39 tbthread_setcancelstate(TBTHREAD_CANCEL_DISABLE, 0);
40 tbthread_cleanup_push(cleanup, self);
41 tbprint("[thread 0x%llx] Running the once function\n", self);
42 if(!once_one) {
43 once_thread = self;
44 once_one = 1;
45 }
46 tbthread_setcanceltype(TBTHREAD_CANCEL_ASYNCHRONOUS, 0);
47 tbthread_setcancelstate(TBTHREAD_CANCEL_ENABLE, 0);
48 tbsleep(5);
49}
50
51tbthread_once_t once = TBTHREAD_ONCE_INIT;
52
53//------------------------------------------------------------------------------
54// Thread function
55//------------------------------------------------------------------------------
56void *thread_func(void *arg)
57{
58 tbthread_t self = tbthread_self();
59 tbprint("[thread 0x%llx] About to run the once function\n", self);
60 tbthread_once(&once, once_func);
61 tbprint("[thread 0x%llx] Finished running the once function\n", self);
62 return 0;
63}
64
65//------------------------------------------------------------------------------
66// Start the show
67//------------------------------------------------------------------------------
68int main(int argc, char **argv)
69{
70 tbthread_init();
71
72 tbthread_t thread[5];
73 int targ[5];
74 tbthread_attr_t attr;
75 int st = 0;
76
77 //----------------------------------------------------------------------------
78 // Spawn the threads
79 //----------------------------------------------------------------------------
80 tbthread_attr_init(&attr);
81 for(int i = 0; i < 5; ++i) {
82 targ[i] = i;
83 st = tbthread_create(&thread[i], &attr, thread_func, &targ[i]);
84 if(st != 0) {
85 tbprint("Failed to spawn thread %d: %s\n", i, tbstrerror(-st));
86 goto exit;
87 }
88 }
89
90 tbprint("[thread main] Threads spawned successfully\n");
91 tbsleep(1);
92 tbprint("[thread main] Canceling the once thread: 0x%llx\n", once_thread);
93 tbthread_cancel(once_thread);
94
95 for(int i = 0; i < 5; ++i) {
96 st = tbthread_join(thread[i], 0);
97 if(st != 0) {
98 tbprint("Failed to join thread %d: %s\n", i, tbstrerror(-st));
99 goto exit;
100 }
101 }
102
103 tbprint("[thread main] Threads joined\n");
104
105exit:
106 tbthread_finit();
107 return st;
108};
109