-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFunctionPointerTest.bb
More file actions
218 lines (172 loc) · 5.35 KB
/
Copy pathFunctionPointerTest.bb
File metadata and controls
218 lines (172 loc) · 5.35 KB
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
Strict
EnableGC
Global counter = 0
; For calls using function pointers if you need to pass or recieve more than a single integer
; You need to use DTO objects
Type BasicDTO
Field var%
Method create.BasicDTO(var%)
self\var = var
return self
End Method
End Type
Function resetGlobals()
; Reset state
counter = 0
End Function
Function testFunction@(getPtr=False)
if (getPtr)
return FunctionPtr()
end if
counter = 1
Return new BasicDTO(1)
End Function
Function intenseFunction@(arg.BasicDTO=Null)
if (arg = Null)
return FunctionPtr()
end if
delay 100
counter = arg\var
Return new BasicDTO(arg\var)
End Function
Function secondTestFunction@( dto.BasicDTO=Null )
if (dto = Null)
return FunctionPtr()
end if
counter = dto\var
Return new BasicDTO(dto\var)
End Function
Function thirdTestFunction@( arg.BasicDTO=Null )
if (arg = Null)
return FunctionPtr()
end if
delay 20
Local var = arg\var + 1
return new BasicDTO(var)
End Function
Function fourthTestFunction@( threadPtr.BBThread=Null )
if (threadPtr = Null)
return FunctionPtr()
end if
Local result.BasicDTO = Await(threadPtr)
Local var = result\var + 1
return new BasicDTO(var)
End Function
Function launchAsyncIdentity.BBThread(dto.BasicDTO)
Local f_ptr.BBFunction = thirdTestFunction()
Return Async(f_ptr, dto)
End Function
Function launchAsyncThenIdentity.BBThread(dto.BasicDTO)
Local f_ptr.BBFunction = thirdTestFunction()
Local f_ptr_2.BBFunction = fourthTestFunction()
Local t_ptr.BBThread = Async(f_ptr, dto)
Return AsyncThen(t_ptr, f_ptr_2)
End Function
Function clobberFunctionPointerStack()
Local a0 = 100
Local a1 = 101
Local a2 = 102
Local a3 = 103
Local a4 = 104
Local a5 = 105
Local a6 = 106
Local a7 = 107
For i = 0 To 256
a0 = a0 + i
a1 = a1 + a0
a2 = a2 + a1
a3 = a3 + a2
a4 = a4 + a3
a5 = a5 + a4
a6 = a6 + a5
a7 = a7 + a6
Next
Assert(a7 <> 107)
End Function
Test testFunctionPointer()
Local f_ptr = testFunction(true) ; To get a pointer of a function you have to call the function and return the pointer
Assert(NOT f_ptr = 0)
Local value.BasicDTO = testFunction()
Assert(value\var = 1)
Assert(counter = 1)
; Reset state
resetGlobals()
End Test
Test testCallPointer()
; You can pass a null object signaling you only want the function pointer returned
Local f_ptr.BBFunction = secondTestFunction(Null)
Assert(NOT f_ptr = Null)
; Craft a DTO object to send to the pointer
Local dto.BasicDTO = new BasicDTO(1)
; The function need to work with Ptrs so cast your DTO to a Ptr and then use Ptr to cast back the returned DTO
Local result.BasicDTO = Call(f_ptr, Ptr dto)
Assert(result\var = 1)
Assert(counter = 1)
; Reset state
resetGlobals()
End Test
Test testThread()
Local f_ptr.BBFunction = testFunction(true)
Assert(NOT f_ptr = Null)
Local f_ptr_2.BBFunction = intenseFunction(Null)
Assert(NOT f_ptr_2 = Null)
; You can asyncronously call function pointers as well
Local thread.BBThread = Async (f_ptr_2, new BasicDTO(2))
Assert(counter = 0)
; The above will return with a future variable so you can run other code on the main thread while waiting for it's value
testFunction()
Assert(counter = 1)
; You can also pause the current thread while you wait for the future variable to populate
Local result.BasicDTO = Await (thread)
Assert(counter = 2)
Assert(result\var = 2)
resetGlobals()
End Test
Test testThreadPoll()
Local f_ptr.BBFunction = intenseFunction(Null)
Assert(NOT f_ptr = Null)
Local thread.BBThread = Async (f_ptr, new BasicDTO(2))
Assert(counter = 0)
Local checkCount = 0
while(true)
; Poll allows for checking if a thread is ready to return a value so you don't have to block
; the current thread just to check if it is ready and then await will return the value immediately.
if (Poll(thread))
Local result.BasicDTO = Await(thread)
Assert(counter = 2)
Assert(result\var = 2)
Exit
end if
checkCount = checkCount + 1
wend
Assert(checkCount > 0)
resetGlobals()
End Test
Test testThen()
Local f_ptr.BBFunction = thirdTestFunction()
Local f_ptr_2.BBFunction = fourthTestFunction()
Local t_ptr.BBThread = Async(f_ptr, new BasicDTO(1))
Local t_ptr_2.BBThread = AsyncThen(t_ptr, f_ptr_2)
Local result.BasicDTO = Await(t_ptr_2)
Assert(result\var = 3)
End Test
Test testThreadPayloadOutlivesLauncher()
Local t1.BBThread = launchAsyncIdentity(new BasicDTO(101))
clobberFunctionPointerStack()
Local r1.BasicDTO = Await(t1)
Assert(r1\var = 102)
Local t2.BBThread = launchAsyncIdentity(new BasicDTO(202))
clobberFunctionPointerStack()
Local r2.BasicDTO = Await(t2)
Assert(r2\var = 203)
End Test
Test testThenPayloadOutlivesLauncher()
Local t1.BBThread = launchAsyncThenIdentity(new BasicDTO(11))
clobberFunctionPointerStack()
Local r1.BasicDTO = Await(t1)
Assert(r1\var = 13)
Local t2.BBThread = launchAsyncThenIdentity(new BasicDTO(22))
clobberFunctionPointerStack()
Local r2.BasicDTO = Await(t2)
Assert(r2\var = 24)
End Test