test_rangelock.rs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // -*- coding: utf-8 -*-
  2. //
  3. // Copyright 2021-2023 Michael Büsch <m@bues.ch>
  4. //
  5. // Licensed under the Apache License version 2.0
  6. // or the MIT license, at your option.
  7. // SPDX-License-Identifier: Apache-2.0 OR MIT
  8. //
  9. use range_lock::VecRangeLock;
  10. use std::sync::{Arc, Barrier};
  11. use std::thread;
  12. #[test]
  13. fn test_rangelock() {
  14. // The data that will simultaneously be accessed from the threads.
  15. let data = vec![10, 11, 12, 13];
  16. // Embed the data in a VecRangeLock
  17. // and clone atomic references to it for the threads.
  18. let data_lock0 = Arc::new(VecRangeLock::new(data));
  19. let data_lock1 = Arc::clone(&data_lock0);
  20. let data_lock2 = Arc::clone(&data_lock0);
  21. // Thread barrier, only for demonstration purposes.
  22. let barrier0 = Arc::new(Barrier::new(2));
  23. let barrier1 = Arc::clone(&barrier0);
  24. thread::scope(|s| {
  25. // Spawn first thread.
  26. s.spawn(move || {
  27. {
  28. let mut guard = data_lock0.try_lock(0..2).expect("T0: Failed to lock 0..2");
  29. guard[0] = 100; // Write to data[0]
  30. }
  31. barrier0.wait(); // Synchronize with second thread.
  32. {
  33. let guard = data_lock0.try_lock(2..4).expect("T0: Failed to lock 2..4");
  34. assert_eq!(guard[0], 200); // Read from data[2]
  35. }
  36. });
  37. // Spawn second thread.
  38. s.spawn(move || {
  39. {
  40. let mut guard = data_lock1.try_lock(2..4).expect("T1: Failed to lock 2..4");
  41. guard[0] = 200; // Write to data[2]
  42. }
  43. barrier1.wait(); // Synchronize with first thread.
  44. {
  45. let guard = data_lock1.try_lock(0..2).expect("T1: Failed to lock 0..2");
  46. assert_eq!(guard[0], 100); // Read from data[0]
  47. }
  48. });
  49. });
  50. // Unwrap the data from the lock.
  51. let data = Arc::try_unwrap(data_lock2)
  52. .expect("Arc unwrap failed")
  53. .into_inner();
  54. // Check the data that has been modified by the threads.
  55. assert_eq!(data, vec![100, 11, 200, 13]);
  56. }
  57. #[test]
  58. fn test_conflict() {
  59. let data = vec![10, 11, 12, 13];
  60. let data_lock0 = Arc::new(VecRangeLock::new(data));
  61. let data_lock1 = Arc::clone(&data_lock0);
  62. let barrier0 = Arc::new(Barrier::new(2));
  63. let barrier1 = Arc::clone(&barrier0);
  64. thread::scope(|s| {
  65. s.spawn(move || {
  66. let mut _guard = data_lock0.try_lock(0..2).expect("T0: Failed to lock 0..2");
  67. barrier0.wait();
  68. // try_lock() conflict happens in second thread.
  69. barrier0.wait();
  70. });
  71. s.spawn(move || {
  72. barrier1.wait();
  73. // thread0 holds lock to 0..2, which conflicts with 1..4.
  74. assert!(data_lock1.try_lock(1..4).is_err());
  75. barrier1.wait();
  76. });
  77. });
  78. }
  79. // vim: ts=4 sw=4 expandtab