neuromorphic_drivers/
configuration.rs1pub struct Flagged<Configuration> {
2 configuration: Configuration,
3 updated: bool,
4}
5
6pub struct Updater<Configuration> {
7 flagged_configuration_and_condition:
8 std::sync::Arc<(std::sync::Mutex<Flagged<Configuration>>, std::sync::Condvar)>,
9 thread: Option<std::thread::JoinHandle<()>>,
10 running: std::sync::Arc<std::sync::atomic::AtomicBool>,
11}
12
13impl<Configuration: Clone + Send + 'static> Updater<Configuration> {
14 pub fn new<ContextType, Update>(
15 initial_configuration: Configuration,
16 context: ContextType,
17 update: Update,
18 ) -> Self
19 where
20 ContextType: Send + 'static,
21 Update: Fn(ContextType, &Configuration, &Configuration) -> ContextType + Send + 'static,
22 {
23 let previous_configuration = initial_configuration.clone();
24 let flagged_configuration_and_condition = std::sync::Arc::new((
25 std::sync::Mutex::new(Flagged {
26 configuration: initial_configuration,
27 updated: false,
28 }),
29 std::sync::Condvar::new(),
30 ));
31 let thread_flagged_configuration_and_condition =
32 flagged_configuration_and_condition.clone();
33 let running = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true));
34 let thread_running = running.clone();
35 Self {
36 flagged_configuration_and_condition,
37 thread: Some(std::thread::spawn(move || {
38 let mut context = context;
39 let mut previous_configuration = previous_configuration;
40 while thread_running.load(std::sync::atomic::Ordering::Acquire) {
41 let configuration = {
42 let (lock, condvar) = &*thread_flagged_configuration_and_condition;
43 let mut flagged_configuration = lock
44 .lock()
45 .expect("flagged configuration mutex is not poisoned");
46 if !flagged_configuration.updated {
47 flagged_configuration = condvar
48 .wait_timeout(
49 flagged_configuration,
50 std::time::Duration::from_millis(100),
51 )
52 .expect("flagged configuration mutex is not poisoned")
53 .0;
54 }
55 if flagged_configuration.updated {
56 flagged_configuration.updated = false;
57 Some(flagged_configuration.configuration.clone())
58 } else {
59 None
60 }
61 };
62 if let Some(configuration) = configuration {
63 context = update(context, &previous_configuration, &configuration);
64 previous_configuration = configuration;
65 }
66 }
67 })),
68 running,
69 }
70 }
71
72 pub fn update(&self, configuration: Configuration) {
73 let (lock, condvar) = &*self.flagged_configuration_and_condition;
74 let mut flagged_configuration = lock
75 .lock()
76 .expect("flagged configuration mutex is not poisoned");
77 flagged_configuration.configuration = configuration;
78 flagged_configuration.updated = true;
79 condvar.notify_one();
80 }
81
82 pub fn current_configuration(&self) -> Configuration {
83 self.flagged_configuration_and_condition
84 .0
85 .lock()
86 .expect("flagged configuration mutex is not poisoned")
87 .configuration
88 .clone()
89 }
90}
91
92impl<Configuration> Drop for Updater<Configuration> {
93 fn drop(&mut self) {
94 self.running
95 .store(false, std::sync::atomic::Ordering::Release);
96 if let Some(thread) = self.thread.take() {
97 thread.join().expect("not joining self");
98 }
99 }
100}