Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: mojo/public/rust/src/bindings/run_loop.rs

Issue 2220183003: Rust: Add validation to decode (Closed) Base URL: git@github.com:domokit/mojo.git@coder-testing
Patch Set: Update from upstream branches (fixed arrays, validation code, etc.) Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/public/rust/src/bindings/mojom.rs ('k') | mojo/public/rust/tests/encoding.rs » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 //! This module contains a thread-local run-loop. 5 //! This module contains a thread-local run-loop.
6 //! 6 //!
7 //! The run-loop may have handles and handlers pre-registers 7 //! The run-loop may have handles and handlers pre-registers
8 //! (and in fact, must) in order to keep running. The run-loop 8 //! (and in fact, must) in order to keep running. The run-loop
9 //! executes until it has no more handles or handlers on itself, 9 //! executes until it has no more handles or handlers on itself,
10 //! or until it is told to quit via stop(). 10 //! or until it is told to quit via stop().
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 converted = (deadline as system::MojoTimeTicks) + now 200 converted = (deadline as system::MojoTimeTicks) + now
201 } 201 }
202 } 202 }
203 converted 203 converted
204 } 204 }
205 205
206 /// Convert an absolute deadline to a mojo deadline which is relative to some 206 /// Convert an absolute deadline to a mojo deadline which is relative to some
207 /// notion of "now". 207 /// notion of "now".
208 /// 208 ///
209 /// If the deadline is earlier than "now", this routine rounds up to "now". 209 /// If the deadline is earlier than "now", this routine rounds up to "now".
210 fn relative_deadline(deadline: system::MojoTimeTicks, now: system::MojoTimeTicks ) -> system::MojoDeadline { 210 fn relative_deadline(deadline: system::MojoTimeTicks,
211 now: system::MojoTimeTicks)
212 -> system::MojoDeadline {
211 if deadline == MOJO_INDEFINITE_ABSOLUTE { 213 if deadline == MOJO_INDEFINITE_ABSOLUTE {
212 MOJO_INDEFINITE 214 MOJO_INDEFINITE
213 } else if now >= deadline { 215 } else if now >= deadline {
214 0 216 0
215 } else { 217 } else {
216 (deadline - now) as system::MojoDeadline 218 (deadline - now) as system::MojoDeadline
217 } 219 }
218 } 220 }
219 221
220 /// This structure contains all information necessary to wait on handles 222 /// This structure contains all information necessary to wait on handles
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 { 282 {
281 283
282 let token = self.generate_token(); 284 let token = self.generate_token();
283 let abs_deadline = absolute_deadline(deadline); 285 let abs_deadline = absolute_deadline(deadline);
284 self.handle_set.add(handle, signals, token.as_cookie(), wsflags!(Add::No ne)); 286 self.handle_set.add(handle, signals, token.as_cookie(), wsflags!(Add::No ne));
285 self.deadlines.push(DeadlineInfo { 287 self.deadlines.push(DeadlineInfo {
286 token: token.clone(), 288 token: token.clone(),
287 deadline: abs_deadline, 289 deadline: abs_deadline,
288 }); 290 });
289 debug_assert!(!self.handlers.contains_key(&token)); 291 debug_assert!(!self.handlers.contains_key(&token));
290 self.handlers.insert(token.clone(), HandlerInfo { 292 self.handlers.insert(token.clone(),
291 handle: handle.get_native_handle(), 293 HandlerInfo {
292 handler: Some(Box::new(handler)), 294 handle: handle.get_native_handle(),
293 deadline: abs_deadline, 295 handler: Some(Box::new(handler)),
294 }); 296 deadline: abs_deadline,
297 });
295 token 298 token
296 } 299 }
297 300
298 /// Updates the signals and deadline of an existing handler in the 301 /// Updates the signals and deadline of an existing handler in the
299 /// runloop via token. The token remains unchanged and valid. 302 /// runloop via token. The token remains unchanged and valid.
300 /// 303 ///
301 /// Returns true on a successful update and false if the token was not 304 /// Returns true on a successful update and false if the token was not
302 /// found. 305 /// found.
303 pub fn reregister(&mut self, 306 pub fn reregister(&mut self,
304 token: &Token, 307 token: &Token,
(...skipping 16 matching lines...) Expand all
321 }); 324 });
322 // Acquire the raw handle held by the HandlerInfo in order to 325 // Acquire the raw handle held by the HandlerInfo in order to
323 // call the wait_set's add method. Invalidate it immediately aft er 326 // call the wait_set's add method. Invalidate it immediately aft er
324 // in order to prevent the handle from being closed. 327 // in order to prevent the handle from being closed.
325 // 328 //
326 // It's perfectly okay for the handle to be invalid, so although this 329 // It's perfectly okay for the handle to be invalid, so although this
327 // is all unsafe, the whole system should just call the handler with an 330 // is all unsafe, the whole system should just call the handler with an
328 // error. 331 // error.
329 let mut dummy = unsafe { system::acquire(info.handle()) }; 332 let mut dummy = unsafe { system::acquire(info.handle()) };
330 self.handle_set.add(&dummy, signals, token.as_cookie(), wsflags! (Add::None)); 333 self.handle_set.add(&dummy, signals, token.as_cookie(), wsflags! (Add::None));
331 unsafe { dummy.invalidate(); } 334 unsafe {
335 dummy.invalidate();
336 }
332 true 337 true
333 }, 338 }
334 None => false, 339 None => false,
335 } 340 }
336 } 341 }
337 342
338 /// Removes an entry from the runloop. 343 /// Removes an entry from the runloop.
339 /// 344 ///
340 /// Since we cannot remove from the deadlines heap, we just leave the deadli ne 345 /// Since we cannot remove from the deadlines heap, we just leave the deadli ne
341 /// in there as "stale", and we handle those when trying to find the next cl osest 346 /// in there as "stale", and we handle those when trying to find the next cl osest
342 /// deadline. 347 /// deadline.
343 pub fn deregister(&mut self, token: Token) -> bool { 348 pub fn deregister(&mut self, token: Token) -> bool {
344 match self.handlers.remove(&token) { 349 match self.handlers.remove(&token) {
345 Some(_) => { 350 Some(_) => {
346 let _result = self.handle_set.remove(token.as_cookie()); 351 let _result = self.handle_set.remove(token.as_cookie());
347 debug_assert_eq!(_result, MojoResult::Okay); 352 debug_assert_eq!(_result, MojoResult::Okay);
348 true 353 true
349 }, 354 }
350 None => false, 355 None => false,
351 } 356 }
352 } 357 }
353 358
354 /// Uses the binary heap to get the next closest deadline. 359 /// Uses the binary heap to get the next closest deadline.
355 /// 360 ///
356 /// Removes stale deadline entries as they are found, but 361 /// Removes stale deadline entries as they are found, but
357 /// does not otherwise modify the heap of deadlines. 362 /// does not otherwise modify the heap of deadlines.
358 fn get_next_deadline(&mut self) -> system::MojoTimeTicks { 363 fn get_next_deadline(&mut self) -> system::MojoTimeTicks {
359 debug_assert!(!self.handlers.is_empty()); 364 debug_assert!(!self.handlers.is_empty());
(...skipping 10 matching lines...) Expand all
370 } 375 }
371 top.deadline() 376 top.deadline()
372 } 377 }
373 378
374 /// Gets a handler by token to be manipulated in a consistent environment. 379 /// Gets a handler by token to be manipulated in a consistent environment.
375 /// 380 ///
376 /// This method provides a method of accessing a handler in order to manipul ate 381 /// This method provides a method of accessing a handler in order to manipul ate
377 /// it in a manner that avoids a borrow cycle, that is, it take()s the handl er 382 /// it in a manner that avoids a borrow cycle, that is, it take()s the handl er
378 /// out of the HashMap, and returns it when manipulation has completed. 383 /// out of the HashMap, and returns it when manipulation has completed.
379 fn get_handler_with<F>(&mut self, token: &Token, invoker: F) 384 fn get_handler_with<F>(&mut self, token: &Token, invoker: F)
380 where F: FnOnce(&mut Self, &mut Box<Handler + 'h>, Token, system::MojoTi meTicks) 385 where F: FnOnce(&mut Self,
386 &mut Box<Handler + 'h>,
387 Token,
388 system::MojoTimeTicks)
381 { 389 {
382 // Logic for pulling out the handler as well as its current deadline. 390 // Logic for pulling out the handler as well as its current deadline.
383 // 391 //
384 // Unfortunately, pulling out the handler value here and "onto the stack " 392 // Unfortunately, pulling out the handler value here and "onto the stack "
385 // (it probably won't actually end up on the stack thanks to optimizatio ns) 393 // (it probably won't actually end up on the stack thanks to optimizatio ns)
386 // is necessary since otherwise the borrow checker complains that we pas s 394 // is necessary since otherwise the borrow checker complains that we pas s
387 // a mutable reference to the RunLoop and the handler (as &mut self) to 395 // a mutable reference to the RunLoop and the handler (as &mut self) to
388 // the callbacks at the same time. This is understandably unsafe since 396 // the callbacks at the same time. This is understandably unsafe since
389 // modifying the hashmap with register and deregister can invalidate the 397 // modifying the hashmap with register and deregister can invalidate the
390 // reference to self in the callback. In the C++ bindings and in other R ust 398 // reference to self in the callback. In the C++ bindings and in other R ust
391 // event loops this is exactly what happens, but I avoided this. The dow nside 399 // event loops this is exactly what happens, but I avoided this. The dow nside
392 // is that we can no longer nest event loop run() calls. Once we put a h andler 400 // is that we can no longer nest event loop run() calls. Once we put a h andler
393 // onto the stack here, we can no longer call its callback in a nested m anner 401 // onto the stack here, we can no longer call its callback in a nested m anner
394 // from the RunLoop. I could just enable nesting with this one restricti on, that 402 // from the RunLoop. I could just enable nesting with this one restricti on, that
395 // the handler calling run() will always be ignored, but this is unintui tive. 403 // the handler calling run() will always be ignored, but this is unintui tive.
396 let (mut handler, deadline) = match self.handlers.get_mut(&token) { 404 let (mut handler, deadline) = match self.handlers.get_mut(&token) {
397 Some(ref_info) => (match ref_info.take() { 405 Some(ref_info) => {
398 Some(handler) => handler, 406 (match ref_info.take() {
399 None => return, 407 Some(handler) => handler,
400 }, ref_info.deadline()), 408 None => return,
409 },
410 ref_info.deadline())
411 }
401 None => return, 412 None => return,
402 }; 413 };
403 // Call the closure that will invoke the callbacks. 414 // Call the closure that will invoke the callbacks.
404 invoker(self, &mut handler, token.clone(), deadline); 415 invoker(self, &mut handler, token.clone(), deadline);
405 // Restore the handler to its location in the HashMap 416 // Restore the handler to its location in the HashMap
406 if let Some(ref_info) = self.handlers.get_mut(&token) { 417 if let Some(ref_info) = self.handlers.get_mut(&token) {
407 ref_info.give(handler); 418 ref_info.give(handler);
408 } 419 }
409 } 420 }
410 421
411 /// For all the results we received, we notify the respective handle 422 /// For all the results we received, we notify the respective handle
412 /// owners of the results by calling their given callbacks. 423 /// owners of the results by calling their given callbacks.
413 /// 424 ///
414 /// We do NOT dequeue notified handles. 425 /// We do NOT dequeue notified handles.
415 fn notify_of_results(&mut self, results: &Vec<system::WaitSetResult>) { 426 fn notify_of_results(&mut self, results: &Vec<system::WaitSetResult>) {
416 debug_assert!(!self.handlers.is_empty()); 427 debug_assert!(!self.handlers.is_empty());
417 for wsr in results.iter() { 428 for wsr in results.iter() {
418 let token = Token(wsr.cookie()); 429 let token = Token(wsr.cookie());
419 self.get_handler_with(&token, move |runloop, boxed_handler, token, _ dl| { 430 self.get_handler_with(&token, move |runloop, boxed_handler, token, _ dl| {
420 let handler = boxed_handler.as_mut(); 431 let handler = boxed_handler.as_mut();
421 match wsr.result() { 432 match wsr.result() {
422 MojoResult::Okay => { 433 MojoResult::Okay => handler.on_ready(runloop, token),
423 handler.on_ready(runloop, token)
424 },
425 MojoResult::Cancelled => { 434 MojoResult::Cancelled => {
426 handler.on_error(runloop, token, WaitError::HandleClosed ) 435 handler.on_error(runloop, token, WaitError::HandleClosed )
427 }, 436 }
428 MojoResult::Busy => { 437 MojoResult::Busy => handler.on_error(runloop, token, WaitErr or::HandleBusy),
429 handler.on_error(runloop, token, WaitError::HandleBusy)
430 },
431 MojoResult::FailedPrecondition => { 438 MojoResult::FailedPrecondition => {
432 handler.on_error(runloop, token, WaitError::Unsatisfiabl e) 439 handler.on_error(runloop, token, WaitError::Unsatisfiabl e)
433 }, 440 }
434 other => panic!("Unexpected result received after waiting: { }", other), 441 other => panic!("Unexpected result received after waiting: { }", other),
435 } 442 }
436 }); 443 });
437 // In order to quit as soon as possible, we should check to quit aft er every 444 // In order to quit as soon as possible, we should check to quit aft er every
438 // potential handler call, as any of them could have signaled to qui t. 445 // potential handler call, as any of them could have signaled to qui t.
439 if self.should_quit { 446 if self.should_quit {
440 break; 447 break;
441 } 448 }
442 } 449 }
443 } 450 }
444 451
445 /// Since the deadline expired, we notify the relevant handle 452 /// Since the deadline expired, we notify the relevant handle
446 /// owners of the expiration by calling their given callbacks. 453 /// owners of the expiration by calling their given callbacks.
447 /// 454 ///
448 /// We do NOT dequeue notified handles. 455 /// We do NOT dequeue notified handles.
449 fn notify_of_expired(&mut self, expired_deadline: system::MojoTimeTicks) { 456 fn notify_of_expired(&mut self, expired_deadline: system::MojoTimeTicks) {
450 debug_assert!(!self.handlers.is_empty()); 457 debug_assert!(!self.handlers.is_empty());
451 let mut top = match self.deadlines.peek() { 458 let mut top = match self.deadlines.peek() {
452 Some(info) => info.clone(), 459 Some(info) => info.clone(),
453 None => panic!("Should not be in notify_of_expired without at least one deadline!"), 460 None => panic!("Should not be in notify_of_expired without at least one deadline!"),
454 }; 461 };
455 while expired_deadline >= top.deadline() { 462 while expired_deadline >= top.deadline() {
456 let next_deadline = top.deadline(); 463 let next_deadline = top.deadline();
457 self.get_handler_with(top.token(), move |runloop, boxed_handler, tok en, expected_dl| { 464 self.get_handler_with(top.token(),
458 let handler = boxed_handler.as_mut(); 465 move |runloop, boxed_handler, token, expected_ dl| {
459 if next_deadline == expected_dl { 466 let handler = boxed_handler.as_mut();
460 handler.on_timeout(runloop, token); 467 if next_deadline == expected_dl {
461 } 468 handler.on_timeout(runloop, token);
462 }); 469 }
470 });
463 // In order to quit as soon as possible, we should check to quit aft er every 471 // In order to quit as soon as possible, we should check to quit aft er every
464 // potential handler call, as any of them could have signaled to qui t. 472 // potential handler call, as any of them could have signaled to qui t.
465 if self.should_quit { 473 if self.should_quit {
466 break; 474 break;
467 } 475 }
468 // Remove the deadline 476 // Remove the deadline
469 self.deadlines.pop(); 477 self.deadlines.pop();
470 // Break if the next deadline has not yet expired. 478 // Break if the next deadline has not yet expired.
471 top = match self.deadlines.peek() { 479 top = match self.deadlines.peek() {
472 Some(info) => info.clone(), 480 Some(info) => info.clone(),
(...skipping 19 matching lines...) Expand all
492 self.notify_of_results(results_buffer); 500 self.notify_of_results(results_buffer);
493 // Clear the buffer since we don't need the results anymore. 501 // Clear the buffer since we don't need the results anymore.
494 // Helps prevent a copy if we resize the buffer. 502 // Helps prevent a copy if we resize the buffer.
495 results_buffer.clear(); 503 results_buffer.clear();
496 // Increase the size of the buffer if there are more results 504 // Increase the size of the buffer if there are more results
497 // we could be holding. 505 // we could be holding.
498 let capacity = results_buffer.capacity(); 506 let capacity = results_buffer.capacity();
499 if capacity < MAXIMUM_WAIT_SET_NUM_RESULTS && capacity < (max_re sults) as usize { 507 if capacity < MAXIMUM_WAIT_SET_NUM_RESULTS && capacity < (max_re sults) as usize {
500 results_buffer.reserve(capacity); 508 results_buffer.reserve(capacity);
501 } 509 }
502 }, 510 }
503 Err(result) => { 511 Err(result) => {
504 assert_eq!(result, MojoResult::DeadlineExceeded); 512 assert_eq!(result, MojoResult::DeadlineExceeded);
505 self.notify_of_expired(deadline); 513 self.notify_of_expired(deadline);
506 }, 514 }
507 } 515 }
508 } 516 }
509 517
510 /// Loop forever until a callback tells us to quit. 518 /// Loop forever until a callback tells us to quit.
511 pub fn run(&mut self) { 519 pub fn run(&mut self) {
512 // It's an error it already be running... 520 // It's an error it already be running...
513 if self.running { 521 if self.running {
514 panic!("RunLoop is already running!"); 522 panic!("RunLoop is already running!");
515 } 523 }
516 self.running = true; 524 self.running = true;
517 self.should_quit = false; 525 self.should_quit = false;
518 let mut buffer: Vec<system::WaitSetResult> = Vec::with_capacity(INITIAL_ WAIT_SET_NUM_RESULTS); 526 let mut buffer: Vec<system::WaitSetResult> =
527 Vec::with_capacity(INITIAL_WAIT_SET_NUM_RESULTS);
519 // Loop while we haven't been signaled to quit, and there's something to wait on. 528 // Loop while we haven't been signaled to quit, and there's something to wait on.
520 while !self.should_quit && !self.handlers.is_empty() { 529 while !self.should_quit && !self.handlers.is_empty() {
521 self.wait(&mut buffer) 530 self.wait(&mut buffer)
522 } 531 }
523 self.running = false; 532 self.running = false;
524 } 533 }
525 534
526 /// Set a flag to quit at the next available moment. 535 /// Set a flag to quit at the next available moment.
527 pub fn quit(&mut self) { 536 pub fn quit(&mut self) {
528 self.should_quit = true; 537 self.should_quit = true;
529 } 538 }
530 } 539 }
531 540
532 /// Provides a scope to modify the current thread's runloop. 541 /// Provides a scope to modify the current thread's runloop.
533 pub fn with_current<F>(modifier: F) 542 pub fn with_current<F>(modifier: F)
534 where F: FnOnce(&mut RunLoop) 543 where F: FnOnce(&mut RunLoop)
535 { 544 {
536 TL_RUN_LOOP.with(|ref_runloop| { 545 TL_RUN_LOOP.with(|ref_runloop| {
537 let mut runloop = ref_runloop.borrow_mut(); 546 let mut runloop = ref_runloop.borrow_mut();
538 modifier(&mut *runloop); 547 modifier(&mut *runloop);
539 }); 548 });
540 } 549 }
OLDNEW
« no previous file with comments | « mojo/public/rust/src/bindings/mojom.rs ('k') | mojo/public/rust/tests/encoding.rs » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698