• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 use super::*;
17 
18 extern crate ylong_runtime;
19 
20 use std::future::Future;
21 use crate::is_handling_transaction;
22 use crate::errors::{IpcStatusCode};
23 
24 /// Use the Ylong `spawn_blocking` pool
25 pub enum Ylong {}
26 
27 impl IpcAsyncPool for Ylong {
spawn<'a, F1, F2, Fut, A, B>(spawn_this: F1, after_handle: F2) -> BoxFuture<'a, IpcResult<B>> where F1: FnOnce() -> A, F2: FnOnce(A) -> Fut, Fut: Future<Output = IpcResult<B>>, F1: Send + 'static, F2: Send + 'a, Fut: Send + 'a, A: Send + 'static, B: Send + 'a,28     fn spawn<'a, F1, F2, Fut, A, B>(spawn_this: F1, after_handle: F2) -> BoxFuture<'a, IpcResult<B>>
29     where
30         F1: FnOnce() -> A,
31         F2: FnOnce(A) -> Fut,
32         Fut: Future<Output = IpcResult<B>>,
33         F1: Send + 'static,
34         F2: Send + 'a,
35         Fut: Send + 'a,
36         A: Send + 'static,
37         B: Send + 'a,
38     {
39         if is_handling_transaction() {
40             // We are currently on the thread pool for a binder server, so we should execute the
41             // transaction on the current thread so that the binder kernel driver is able to apply
42             // its deadlock prevention strategy to the sub-call.
43             //
44             // This shouldn't cause issues with blocking the thread as only one task will run in a
45             // call to `block_on`, so there aren't other tasks to block.
46             let result = spawn_this();
47             Box::pin(after_handle(result))
48         } else {
49             let handle = Runtime::spawn_blocking(spawn_this);
50             Box::pin(async move {
51                 // The `is_panic` branch is not actually reachable in OH as we compile
52                 // with `panic = abort`.
53                 match handle.await {
54                     Ok(res) => after_handle(res).await,
55                     Err(_) => Err(IpcStatusCode::Failed),
56                 }
57             })
58         }
59     }
60 }
61 
62 /// Wrapper around Ylong runtime types for providing a runtime to a binder server.
63 pub struct Runtime;
64 
65 impl IpcAsyncRuntime for Runtime {
spawn<T, R>(task: T) -> JoinHandle<R> where T: Future<Output = R>, T: Send + 'static, R: Send + 'static,66     fn spawn<T, R>(task: T) -> JoinHandle<R>
67     where
68         T: Future<Output = R>,
69         T: Send + 'static,
70         R: Send + 'static,
71     {
72         ylong_runtime::spawn(task)
73     }
74 
spawn_blocking<T, R>(task: T) -> JoinHandle<R> where T: FnOnce() -> R, T: Send + 'static, R: Send + 'static,75     fn spawn_blocking<T, R>(task: T) -> JoinHandle<R>
76     where
77         T: FnOnce() -> R,
78         T: Send + 'static,
79         R: Send + 'static,
80     {
81         ylong_runtime::spawn_blocking(task)
82     }
83 
block_on<F: Future>(future: F) -> F::Output84     fn block_on<F: Future>(future: F) -> F::Output
85     {
86         ylong_runtime::block_on(future)
87     }
88 }
89 
90