Factor out Rust client library for VirtualizationService.
This reduces code duplication, and will also be useful for Rust tests.
Test: ComposHostTestCases compos_key_tests
Change-Id: I13c41d3b2bbe506495b723e7739f3181cb033f0f
diff --git a/vmclient/src/sync.rs b/vmclient/src/sync.rs
new file mode 100644
index 0000000..a265f60
--- /dev/null
+++ b/vmclient/src/sync.rs
@@ -0,0 +1,59 @@
+// Copyright 2022, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+use std::{
+ sync::{Condvar, LockResult, Mutex, MutexGuard, PoisonError, WaitTimeoutResult},
+ time::Duration,
+};
+
+/// A mutex with an associated condition variable.
+#[derive(Debug)]
+pub struct Monitor<T> {
+ pub state: Mutex<T>,
+ pub cv: Condvar,
+}
+
+impl<T> Monitor<T> {
+ /// Creates a new mutex wrapping the given value, and a new condition variable to go with it.
+ pub fn new(state: T) -> Self {
+ Self { state: Mutex::new(state), cv: Condvar::default() }
+ }
+
+ /// Waits on the condition variable while the given condition holds true on the contents of the
+ /// mutex.
+ ///
+ /// Blocks until the condition variable is notified and the function returns false.
+ pub fn wait_while(&self, condition: impl FnMut(&mut T) -> bool) -> LockResult<MutexGuard<T>> {
+ self.cv.wait_while(self.state.lock()?, condition)
+ }
+
+ /// Waits on the condition variable while the given condition holds true on the contents of the
+ /// mutex, with a timeout.
+ ///
+ /// Blocks until the condition variable is notified and the function returns false, or the
+ /// timeout elapses.
+ pub fn wait_timeout_while(
+ &self,
+ timeout: Duration,
+ condition: impl FnMut(&mut T) -> bool,
+ ) -> Result<(MutexGuard<T>, WaitTimeoutResult), PoisonError<MutexGuard<T>>> {
+ self.cv
+ .wait_timeout_while(self.state.lock()?, timeout, condition)
+ .map_err(convert_poison_error)
+ }
+}
+
+fn convert_poison_error<T>(err: PoisonError<(T, WaitTimeoutResult)>) -> PoisonError<T> {
+ PoisonError::new(err.into_inner().0)
+}