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
|
{
This file is part of the Free Pascal run time library.
Copyright (c) 2011 by Jonas Maebe,
member of the Free Pascal development team.
This file implements support routines for threadvarq with FPC/JVM
See the file COPYING.FPC, included in this distribution,
for details about the copyright.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
**********************************************************************}
{ In Java, threadvars are represented by descendnts of java.lang.ThreadLocal.
This class has three important methods: set, get and initialValue.
If you call the "get" method of a JLThreadLocal instance in a thread for the
first time before calling "set", it will call the initialValue method and
return its result. After that, it will return whatever initialValue returned,
or the previous value instated by "set". A JLThreadLocal always keeps track of
a JLObject.
We don't want to translate accesses to threadvars into calls to get/set, since
that would mean that we would
a) have to generate different code in the compiler for read and write
accesses
b) no be able to pass threadvars to var-parameters etc
Instead, we add a method called getReadWriteReference to all of our
descendants classes that returns a pointer to the actual value of the
threadvar for this thread. This results in several cases:
a) For primitive types, we store an array of one element of that ordinal
type.
Their initialValue is simply an array of one element (automatically
initialized to 0).
The pointer returned is the "address" of element 0 (pointers to primitive
types are internally arrays pointing to element 0).
b) For non-dynamic arrays, we store that array itself (all arrays are
internally Java arrays, which descend from JLObject).
When initializing the threadvar on startup, we pass an empty copy of such
an array to the constructor and store it. Their initialValue is a deep
copy of this array, created by fpc_dynarray_copy (it accepts a number of
dimensions, because it also has to work for making a copy of dynamic
arrays whose elements are regular arrays).
The pointer returned is simply the address of the array.
c) For implicit pointer types other than regular arrays, we also store the
implicit pointer itself and keep an initialized empty instance around
that is passed to the constructor.
Their initialValue is a clone of this empty instance (can't use this for
arrays, since it would make a shallow copy of the array). Because of the
way the JLCloneable interface works, we have to call the clone method via
reflection.
The pointer returned is again simply the implicit pointer itself.
d) For all other types, we store an array of JLObject of one element,
similar as with primitive types.
Their initialValue is either nil, or optionally a value passed to the
constructor when creating the JLThreadLocal instance (e.g. an empty
string for unicodestring/ansistring, or the enum instance whose ordinal
value is 0)
The pointer returned is the address of element 0 of the array.
}
type
FpcImplicitPtrThreadVar = class(JLThreadLocal)
protected
{ all implicit pointer types are clonable }
fInstanceToClone: JLObject;
{ don't look up the clone method every time }
fCloneMethod: JLRMethod;
function initialValue: JLObject; override;
public
constructor create(initInstanceToClone: JLObject);
function getReadWriteReference: Pointer;
end;
FpcNormalArrayThreadVar = class sealed (FpcImplicitPtrThreadVar)
protected
fArrDim: longint;
fArrTyp: widechar;
function initialValue: JLObject; override;
public
constructor create(initInstanceToClone: JLObject; arrdim: longint; arrtyp: widechar);
end;
FpcBooleanThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PBoolean;
end;
FpcByteThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PShortint;
end;
FpcShortThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PSmallint;
end;
FpcIntThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PLongint;
end;
FpcLongThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PInt64;
end;
FpcCharThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PWideChar;
end;
FpcFloatThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PSingle;
end;
FpcDoubleThreadVar = class sealed (JLThreadLocal)
protected
function initialValue: JLObject; override;
public
function getReadWriteReference: PDouble;
end;
FpcPointerThreadVar = class sealed (JLThreadLocal)
protected
fInitVal: JLObject;
function initialValue: JLObject; override;
public
function getReadWriteReference: PPointer;
constructor create(initVal: JLObject);overload;
end;
|