-
Notifications
You must be signed in to change notification settings - Fork 7
/
thread.oc
189 lines (145 loc) · 5.71 KB
/
thread.oc
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
//! Simple wrapper around the pthread library
@compiler c_include "unistd.h"
@compiler c_include "pthread.h"
@compiler c_flag "-pthread"
[extern "int"]
enum MutexMode{
Normal = extern("PTHREAD_MUTEX_NORMAL")
Recursive = extern("PTHREAD_MUTEX_RECURSIVE")
Errcheck = extern("PTHREAD_MUTEX_ERRORCHECK")
}
[extern "int"]
enum SchedPolicy{
Normal = extern("SCHED_OTHER")
Fifo = extern("SCHED_FIFO")
RoundRobin = extern("SCHED_RR")
}
[extern "int"]
enum DetachState{
Joinable = extern("PTHREAD_CREATE_JOINABLE")
Detached = extern("PTHREAD_CREATE_DETACHED")
}
typedef CallBackType = fn(untyped_ptr): untyped_ptr
namespace impl {
// Threads
[extern "pthread_t"] struct Thread {}
[extern "pthread_attr_t"] struct ThreadAttr
[extern "pthread_create"] def Thread::create(&this, attr: &ThreadAttr, start_routine: CallBackType, arg: untyped_ptr): i32
[extern "pthread_join"] def Thread::join(this, retval: &untyped_ptr): i32
[extern "pthread_detach"] def Thread::detach(this): i32
[extern "pthread_attr_init"] def ThreadAttr::init(&this): i32
[extern "pthread_attr_destroy"] def ThreadAttr::destroy(&this): i32
[extern "pthread_attr_setstacksize"] def ThreadAttr::setstacksize(&this, tack_size:u64): i32
[extern "pthread_attr_getstacksize"] def ThreadAttr::getstacksize(&this, getss:&i32): i32
[extern "pthread_attr_setdetachstate"] def ThreadAttr::setdetachstate(&this, detachstate: DetachState): i32
[extern "pthread_attr_getdetachstate"] def ThreadAttr::getdetachstate(&this, detachstate: &DetachState): i32
[extern "pthread_attr_setschedpolicy"] def ThreadAttr::setschedpolicy(&this, policy: SchedPolicy): i32
[extern "pthread_attr_getschedpolicy"] def ThreadAttr::getschedpolicy(&this, policy: &SchedPolicy): i32
// Mutex
[extern "pthread_mutex_t"] struct Mutex {}
[extern "pthread_mutexattr_t"] struct MutexAttr {}
[extern "pthread_mutex_init"] def Mutex::init(&this, attr: &MutexAttr): i32
[extern "pthread_mutex_destroy"] def Mutex::destroy(&this): i32
[extern "pthread_mutex_lock"] def Mutex::lock(&this): i32
[extern "pthread_mutex_trylock"] def Mutex::trylock(&this): i32
[extern "pthread_mutex_tryunlock"] def Mutex::tryunlock(&this): i32
[extern "pthread_mutex_unlock"] def Mutex::unlock(&this): i32
[extern "pthread_mutexattr_init"] def MutexAttr::init(&this): i32
[extern "pthread_mutexattr_settype"] def MutexAttr::settype(&this, tty: MutexMode): i32
[extern "pthread_mutexattr_destroy"] def MutexAttr::destroy(&this): i32
// Soon i'll be implementing the conditional variable in this sync package
}
def check(a: i32, msg: str = null) {
import std::libc
if a != 0 {
if msg? {
println(`Error: {msg}: {libc::strerror(a)}`);
} else {
println(`Error: {libc::strerror(a)}`);
}
std::exit(libc::EXIT_FAILURE)
}
}
// This is meant to be independent of the Thread object
[extern "pthread_exit"] def exit(retval: untyped_ptr)
[extern "sleep"] def sleep(seconds: u32)
struct Thread {
tid: impl::Thread
tattr: impl::ThreadAttr
cb: CallBackType
args: untyped_ptr
policy: SchedPolicy
dstate: DetachState
}
// Soon i will make this mutex like rust mutex which also contains the data in which needs to be locked
struct Mutex {
tx: impl::Mutex
attr: impl::MutexAttr
mode: MutexMode
}
def Thread::make(callback: fn(untyped_ptr): untyped_ptr, arg: untyped_ptr = null): Thread {
let thread: Thread
thread.policy = Normal
thread.dstate = Joinable
thread.cb = callback
thread.args = arg
return thread
}
// soon it will be deprecated if if language feature improves and we have varaiadic and template variadic
def Thread::set_attr(&this,stack_size:u64,dstate:DetachState,policy:SchedPolicy){
if .dstate == Joinable and .policy == Normal{
check(.tattr.init())
}
.dstate = dstate
.policy = policy
check(.tattr.setstacksize(stack_size))
check(.tattr.setschedpolicy(.policy))
check(.tattr.setdetachstate(.dstate))
}
def Thread::set_stack(&this, stack_size: u64) {
if .dstate == Joinable and .policy == Normal{
check(.tattr.init())
}
check(.tattr.setstacksize(stack_size))
}
def Thread::set_detach_state(&this, dstate: DetachState = Detached) {
if .dstate == Joinable and .policy == Normal{
check(.tattr.init())
}
.dstate = dstate
check(.tattr.setdetachstate(.dstate))
}
def Thread::set_sched_policy(&this, policy: SchedPolicy) {
if .dstate == Joinable and .policy == Normal {
check(.tattr.init())
}
.policy = policy
check(.tattr.setschedpolicy(.policy))
}
def Thread::start_and_join(&this) {
.start()
.join()
}
def Thread::start(&this) => check(.tid.create(&.tattr, .cb, .args))
def Thread::join(&this, b: &untyped_ptr = null) => check(.tid.join( b))
def Thread::destroy_attr(&this) => check(.tattr.destroy())
def Mutex::make(attrmode:MutexMode = Normal): Mutex {
let mutex: Mutex
mutex.mode = attrmode
// handling the error from here only and giving the errno output as str
check(match attrmode {
Normal => mutex.tx.init(null)
else => {
check(mutex.attr.init(), "Cannot initialize attribute")
check(mutex.attr.settype(mutex.mode))
yield mutex.tx.init(&mutex.attr)
}
})
return mutex
}
def Mutex::get_attr_type(&this): MutexMode => .mode
def Mutex::lock(&this) => check(.tx.lock())
def Mutex::unlock(&this) => check(.tx.unlock())
def Mutex::try_lock(&this): i32 => .tx.trylock()
def Mutex::try_unlock(&this): i32 => .tx.tryunlock()
def Mutex::destroy(&this) => check(.tx.destroy())