/
Thread.pm
81 lines (68 loc) · 2.11 KB
/
Thread.pm
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
# Thread represents an OS-level thread. While it could be used directly, it
# is not the preferred way to work in Perl 6. It's a building block for the
# interesting things.
my class Thread {
# The VM-level thread handle.
has Mu $!vm_thread;
# Is the thread's lifetime bounded by that of the application, such
# that when it exits, so does the thread?
has Bool $.app_lifetime;
# Thread's (user-defined) name.
has Str $.name;
submethod BUILD(
:&code!,
Bool() :$!app_lifetime = False,
Str() :$!name = "<anon>"
--> Nil
) {
$!vm_thread := nqp::newthread(
anon sub THREAD-ENTRY() {
my $*THREAD = self;
CONTROL {
default {
my Mu $vm-ex := nqp::getattr(nqp::decont($_), Exception, '$!ex');
nqp::getcomp('perl6').handle-control($vm-ex);
}
}
code();
},
$!app_lifetime ?? 1 !! 0);
}
method start(Thread:U: &code, *%adverbs) {
Thread.new(:&code, |%adverbs).run()
}
method run(Thread:D:) {
nqp::threadrun($!vm_thread);
self
}
method id(Thread:D:) {
nqp::p6box_i(nqp::threadid($!vm_thread));
}
method finish(Thread:D:) {
nqp::threadjoin($!vm_thread);
self
}
method join(Thread:D:) {
self.finish
}
multi method Numeric(Thread:D:) {
self.id
}
multi method Str(Thread:D:) {
"Thread<$.id>($.name)"
}
multi method gist(Thread:D:) {
"Thread #$.id" ~ ($!name ne '<anon>' ?? " ($!name)" !! '')
}
method yield(Thread:U: --> Nil) {
nqp::threadyield();
}
}
Rakudo::Internals.REGISTER-DYNAMIC: '$*THREAD', {
my $init_thread := nqp::create(Thread);
nqp::bindattr($init_thread, Thread, '$!vm_thread', nqp::currentthread());
nqp::bindattr($init_thread, Thread, '$!app_lifetime', False);
nqp::bindattr($init_thread, Thread, '$!name', 'Initial thread');
PROCESS::<$THREAD> := $init_thread;
}
# vim: ft=perl6 expandtab sw=4