5
5
#include " RNSkDrawView.h"
6
6
7
7
#include < chrono>
8
- #include < condition_variable>
9
- #include < mutex>
8
+ #include < functional>
10
9
11
10
#include " RNSkLog.h"
12
11
@@ -30,38 +29,26 @@ RNSkDrawView::RNSkDrawView(std::shared_ptr<RNSkPlatformContext> context)
30
29
_platformContext (context),
31
30
_infoObject(std::make_shared<RNSkInfoObject>()),
32
31
_timingInfo(std::make_shared<RNSkTimingInfo>()),
33
- _isRemoved(false ) {}
32
+ _isDrawing(new std::timed_mutex())
33
+ {}
34
34
35
35
RNSkDrawView::~RNSkDrawView () {
36
- {
37
- _isRemoved = true ;
38
- // This is a very simple fix to an issue where the view posts a redraw
39
- // function to the javascript thread, and the object is destroyed and then
40
- // the redraw function is called and ends up executing on a destroyed draw
41
- // view. Since _isDrawing is an atomic bool we know that as long as it is
42
- // true we are drawing and should wait.
43
- // It is limited to only wait for 500 milliseconds - if it is stuck we
44
- // might have gotten an exception that caused the flag never to be reset.
45
- milliseconds start = std::chrono::duration_cast<milliseconds>(
46
- system_clock::now ().time_since_epoch ());
47
-
48
- while (_isDrawing == true ) {
49
- milliseconds now = std::chrono::duration_cast<milliseconds>(
50
- system_clock::now ().time_since_epoch ());
51
- if (now.count () - start.count () > 500 ) {
52
- RNSkLogger::logToConsole (" Timed out waiting for RNSkDrawView delete..." );
53
- break ;
54
- }
55
- }
36
+ invalidate ();
37
+
38
+ // Wait for the drawing lock (if set)
39
+ if (!_isDrawing->try_lock_for (system_clock::now ().time_since_epoch () + milliseconds (500 ))) {
40
+ RNSkLogger::logToConsole (" Failed to delete since drawing is still locked for native view with id %i" , _nativeId);
56
41
}
42
+
43
+ delete _isDrawing;
57
44
}
58
45
59
- void RNSkDrawView::setIsRemoved () {
60
- _isRemoved = true ;
46
+ void RNSkDrawView::invalidate () {
61
47
endDrawingLoop ();
48
+ _isValid = false ;
62
49
}
63
50
64
- void RNSkDrawView::setDrawCallback (size_t nativeId, std::shared_ptr<jsi::Function> callback) {
51
+ void RNSkDrawView::setDrawCallback (std::shared_ptr<jsi::Function> callback) {
65
52
66
53
if (callback == nullptr ) {
67
54
_drawCallback = nullptr ;
@@ -70,9 +57,6 @@ void RNSkDrawView::setDrawCallback(size_t nativeId, std::shared_ptr<jsi::Functio
70
57
return ;
71
58
}
72
59
73
- // Update native id
74
- _nativeId = nativeId;
75
-
76
60
// Reset timing info
77
61
_timingInfo->reset ();
78
62
@@ -82,7 +66,7 @@ void RNSkDrawView::setDrawCallback(size_t nativeId, std::shared_ptr<jsi::Functio
82
66
int height, double timestamp,
83
67
std::shared_ptr<RNSkPlatformContext> context) {
84
68
auto runtime = context->getJsRuntime ();
85
-
69
+
86
70
// Update info parameter
87
71
_infoObject->beginDrawCallback (width, height, timestamp);
88
72
@@ -134,7 +118,7 @@ void RNSkDrawView::drawInSurface(sk_sp<SkSurface> surface, int width,
134
118
std::shared_ptr<RNSkPlatformContext> context) {
135
119
136
120
try {
137
- if (getIsRemoved ()) {
121
+ if (! isValid ()) {
138
122
return ;
139
123
}
140
124
@@ -177,49 +161,50 @@ void RNSkDrawView::updateTouchState(const std::vector<RNSkTouchPoint> &points) {
177
161
}
178
162
}
179
163
180
- void RNSkDrawView::requestRedraw () {
181
- if (!isReadyToDraw ()) {
182
- _redrawRequestCounter++;
183
- return ;
184
- }
185
-
186
- _isDrawing = true ;
187
-
188
- auto performDraw = [this ]() {
189
- if (getIsRemoved ()) {
190
- RNSkLogger::logToConsole (" Warning: Trying to redraw after delete!" );
191
- _isDrawing = false ;
192
- return ;
193
- }
194
-
195
- if (_drawingMode == RNSkDrawingMode::Continuous) {
196
- _isDrawing = false ;
197
- beginDrawingLoop ();
198
- return ;
199
- }
200
-
201
- milliseconds ms = std::chrono::duration_cast<milliseconds>(
164
+ void RNSkDrawView::performDraw () {
165
+ if (isValid ()) {
166
+ // Calculate milliseconds since start
167
+ milliseconds ms = duration_cast<milliseconds>(
202
168
system_clock::now ().time_since_epoch ());
203
-
169
+
170
+ // Call draw frame method in sub class
204
171
drawFrame (ms.count () / 1000.0 );
205
-
206
- _isDrawing = false ;
207
-
208
- if (_redrawRequestCounter > 0 ) {
172
+
173
+ // Unlock the drawing lock
174
+ _isDrawing->unlock ();
175
+
176
+ // Should we request a new redraw?
177
+ if (_drawingMode != RNSkDrawingMode::Continuous && _redrawRequestCounter > 0 ) {
209
178
_redrawRequestCounter = 0 ;
210
179
requestRedraw ();
211
180
}
212
- };
213
-
214
- _platformContext-> runOnJavascriptThread (performDraw);
181
+ } else {
182
+ _isDrawing-> unlock ();
183
+ }
215
184
}
216
185
217
- bool RNSkDrawView::isReadyToDraw () {
218
- if (_isDrawing) {
219
- return false ;
186
+ void RNSkDrawView::requestRedraw () {
187
+ if (!isReadyToDraw ()) {
188
+ return ;
189
+ }
190
+
191
+ // If we are in continuous mode, we can just start the drawing loop
192
+ if (_drawingMode == RNSkDrawingMode::Continuous) {
193
+ beginDrawingLoop ();
194
+ return ;
220
195
}
196
+
197
+ // Check if we are already in a draw
198
+ if (!_isDrawing->try_lock ()) {
199
+ _redrawRequestCounter++;
200
+ return ;
201
+ }
202
+
203
+ _platformContext->runOnJavascriptThread (std::bind (&RNSkDrawView::performDraw, this ));
204
+ }
221
205
222
- if (getIsRemoved ()) {
206
+ bool RNSkDrawView::isReadyToDraw () {
207
+ if (!isValid ()) {
223
208
return false ;
224
209
}
225
210
@@ -237,58 +222,40 @@ bool RNSkDrawView::isReadyToDraw() {
237
222
}
238
223
239
224
void RNSkDrawView::beginDrawingLoop () {
240
- if (getIsRemoved ()) {
225
+ if (! isValid ()) {
241
226
return ;
242
227
}
243
228
244
- if (_drawingLoopId != - 1 ) {
229
+ if (_drawingLoopId != 0 || _nativeId == 0 ) {
245
230
return ;
246
231
}
247
232
248
233
// Set to zero to avoid calling beginDrawLoop before we return
249
- _drawingLoopId = 0 ;
250
234
_drawingLoopId =
251
235
_platformContext->beginDrawLoop (_nativeId, [this ]() {
252
- auto performDraw = [&]() {
253
- if (getIsRemoved ()) {
254
- return ;
255
- }
256
-
257
- milliseconds ms = std::chrono::duration_cast<milliseconds>(
258
- system_clock::now ().time_since_epoch ());
259
-
260
- // Only redraw if view is still alive
261
- drawFrame (ms.count () / 1000.0 );
262
-
263
- _isDrawing = false ;
264
- };
265
-
266
- if (!isReadyToDraw ()) {
267
- return ;
236
+ if (_isDrawing->try_lock ()) {
237
+ _platformContext->runOnJavascriptThread (std::bind (&RNSkDrawView::performDraw, this ));
268
238
}
269
-
270
- _isDrawing = true ;
271
- _platformContext->runOnJavascriptThread (performDraw);
272
239
});
273
240
}
274
241
275
242
void RNSkDrawView::endDrawingLoop () {
276
- _platformContext->endDrawLoop (_nativeId);
277
- _drawingLoopId = -1 ;
243
+ if (_drawingLoopId != 0 ) {
244
+ _drawingLoopId = 0 ;
245
+ _platformContext->endDrawLoop (_nativeId);
246
+ }
278
247
}
279
248
280
249
void RNSkDrawView::setDrawingMode (RNSkDrawingMode mode) {
281
- if (getIsRemoved () ) {
250
+ if (! isValid () || mode == _drawingMode || _nativeId == 0 ) {
282
251
return ;
283
252
}
284
- if (mode != _drawingMode) {
285
- _drawingMode = mode;
286
- if (mode == RNSkDrawingMode::Default) {
287
- endDrawingLoop ();
288
- } else {
289
- beginDrawingLoop ();
290
- requestRedraw ();
291
- }
253
+ _drawingMode = mode;
254
+ if (mode == RNSkDrawingMode::Default) {
255
+ endDrawingLoop ();
256
+ } else {
257
+ beginDrawingLoop ();
258
+ requestRedraw ();
292
259
}
293
260
}
294
261
0 commit comments