forked from rubinius/rubinius
-
Notifications
You must be signed in to change notification settings - Fork 0
/
thread.hpp
248 lines (195 loc) · 6.2 KB
/
thread.hpp
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
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#ifndef RBX_BUILTIN_THREAD_HPP
#define RBX_BUILTIN_THREAD_HPP
#include "vm/exception.hpp"
#include "vm/type_info.hpp"
#include "builtin/object.hpp"
#include "builtin/randomizer.hpp"
#include "builtin/lookuptable.hpp"
#include "executor.hpp"
namespace rubinius {
class Channel;
class Exception;
/**
* Ruby Thread implementation.
*
* Each Thread is backed by a native thread. This class
* provides the interface Ruby expects to see to manipulate
* Thread execution.
*/
class Thread : public Object {
/** Thread is created and valid and not yet done? */
Object* alive_; // slot
/** Thread is currently sleeping and not running? */
Object* sleep_; // slot
Channel* control_channel_; // slot
/** LookupTable of objects that contain themselves. */
LookupTable* recursive_objects_; // slot
Thread* debugger_thread_; // slot
Fixnum* thread_id_; // slot
Randomizer* randomizer_; // slot
LookupTable* locals_; // slot
thread::SpinLock init_lock_;
/// The VM state for this thread and this thread alone
VM* vm_;
typedef Object* (*Run)(STATE);
Run runner_;
public:
const static object_type type = ThreadType;
static void init(State* state);
public:
attr_accessor(alive, Object);
attr_accessor(sleep, Object);
attr_accessor(control_channel, Channel);
attr_accessor(recursive_objects, LookupTable);
attr_accessor(debugger_thread, Thread);
attr_accessor(thread_id, Fixnum);
attr_accessor(randomizer, Randomizer);
attr_accessor(locals, LookupTable);
VM* vm() {
return vm_;
}
public:
/**
* Allocate a Thread object.
*
* Object is in a valid but not running state.
* It still assumes that #initialize will be
* called to fully set it up. The object is
* not yet associated with an actual native
* thread.
*
* This method also creates a new VM object
* to represent its state.
*
* @see Thread::fork()
* @see Thread::create()
*
* @see vm/vm.hpp
* @see kernel/bootstrap/thread.rb
*/
// Rubinius.primitive :thread_allocate
static Thread* allocate(STATE, Object* self);
/**
* Returns the Thread object for the state.
*
* This is the currently executing Thread.
*/
// Rubinius.primitive :thread_current
static Thread* current(STATE);
/**
* Attempt to schedule some other Thread.
*/
// Rubinius.primitive :thread_pass
static Object* pass(STATE, CallFrame* calling_environment);
public: /* Instance primitives */
/**
* Execute the Thread.
*
* Actually creates the native thread and starts it.
* The native thread will start executing this Thread's
* #__run__ method.
*
* @see Thread::allocate()
*
* @see kernel/bootstrap/thread.rb
*/
// Rubinius.primitive :thread_fork
Object* fork(STATE);
/**
* Execute the Thread.
*
* This leaves the thread in an attached state, so that
* a pthread_join() later on will work.
*/
int fork_attached(STATE);
/**
* Retrieve the priority set for this Thread.
*
* The value is numeric, higher being more important
* but otherwise *potentially* platform-specific for
* any other connotations.
*/
// Rubinius.primitive :thread_priority
Object* priority(STATE);
/**
* Process an exception raised for this Thread.
*/
// Rubinius.primitive :thread_raise
Object* raise(STATE, GCToken gct, Exception* exc);
/**
* Set the priority for this Thread.
*
* The value is numeric, higher being more important
* but otherwise *potentially* platform-specific for
* any other connotations.
*/
// Rubinius.primitive :thread_set_priority
Object* set_priority(STATE, Fixnum* priority);
/**
* Schedule Thread to be run.
*
* This wakes up a sleeping Thread, although it can also
* be invoked on an already-running Thread. The Thread
* is queued to be run, although not necessarily immediately.
*/
// Rubinius.primitive :thread_wakeup
Thread* wakeup(STATE, GCToken gct);
// Rubinius.primitive :thread_context
Tuple* context(STATE);
// Rubinius.primitive :thread_join
Object* join(STATE, GCToken gct, CallFrame* calling_environment);
// Rubinius.primitive :thread_set_critical
static Object* set_critical(STATE, Object* obj);
// Rubinius.primitive :thread_unlock_locks
Object* unlock_locks(STATE, GCToken gct);
/**
* Retrieve a value store in the thread locals.
* This is done in a primitive because it also has
* to consider any running fibers.
*/
// Rubinius.primitive :thread_locals_aref
Object* locals_aref(STATE, Symbol* key);
/**
* Store a value in the thread locals.
* This is done in a primitive because it also has
* to consider any running fibers.
*/
// Rubinius.primitive :thread_locals_store
Object* locals_store(STATE, Symbol* key, Object* value);
/**
* Retrieve the keys for all thread locals.
* This is done in a primitive because it also has
* to consider any running fibers.
*/
// Rubinius.primitive :thread_locals_keys
Array* locals_keys(STATE);
/**
* Check whether a given key has a value store in the thread locals.
* This is done in a primitive because it also has
* to consider any running fibers.
*/
// Rubinius.primitive :thread_locals_has_key
Object* locals_has_key(STATE, Symbol* key);
void init_lock();
void cleanup();
/**
* Create a Thread object.
*
* Used by the Thread::allocate() primitive, creates
* the Thread object and associates it with the provided
* VM state object. The Thread is not yet associated
* with a native thread.
*
* @see Thread::allocate().
*/
static Thread* create(STATE, VM* target, Object* self, Run runner,
bool main_thread = false);
static void* in_new_thread(void*);
public: /* TypeInfo */
class Info : public TypeInfo {
public:
BASIC_TYPEINFO(TypeInfo)
};
};
}
#endif