fory_core/serializer/
mutex.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Serialization support for `Mutex<T>`.
19//!
20//! This module implements [`Serializer`] and [`ForyDefault`] for [`std::sync::Mutex<T>`].
21//! It allows thread-safe mutable containers to be part of serialized graphs.
22//!
23//! Unlike [`std::rc::Rc`] and [`std::sync::Arc`], `Mutex` does not do reference counting, so this wrapper relies
24//! on the serialization of the contained `T` only.
25//!
26//! This is commonly used together with `Arc<Mutex<T>>` in threaded graph structures.
27//!
28//! # Example
29//! ```rust
30//! use std::sync::Mutex;
31//! use fory_core::{Serializer, ForyDefault};
32//!
33//! let mutex = Mutex::new(42);
34//! // Can be serialized by the Fory framework
35//! ```
36//!
37//! # Caveats
38//!
39//! - Serialization locks the mutex while reading/writing the inner value.
40//! - If another thread holds the lock during serialization, this may block indefinitely.
41//!   You should serialize in a quiescent state with no concurrent mutation.
42//! - A poisoned mutex (from a panicked holder) will cause `.lock().unwrap()` to panic
43//!   during serialization — it is assumed this is a programmer error.
44use crate::error::Error;
45use crate::resolver::context::{ReadContext, WriteContext};
46use crate::resolver::type_resolver::{TypeInfo, TypeResolver};
47use crate::serializer::{ForyDefault, Serializer};
48use crate::types::TypeId;
49use std::rc::Rc;
50use std::sync::Mutex;
51
52/// `Serializer` impl for `Mutex<T>`
53///
54/// Simply delegates to the serializer for `T`, allowing thread-safe interior mutable
55/// containers to be included in serialized graphs.
56impl<T: Serializer + ForyDefault> Serializer for Mutex<T> {
57    #[inline(always)]
58    fn fory_write(
59        &self,
60        context: &mut WriteContext,
61        write_ref_data: bool,
62        write_type_info: bool,
63        has_generics: bool,
64    ) -> Result<(), Error> {
65        // Don't add ref tracking for Mutex itself, just delegate to inner type
66        // The inner type will handle its own ref tracking
67        let guard = self.lock().unwrap();
68        T::fory_write(
69            &*guard,
70            context,
71            write_ref_data,
72            write_type_info,
73            has_generics,
74        )
75    }
76
77    #[inline(always)]
78    fn fory_write_data_generic(
79        &self,
80        context: &mut WriteContext,
81        has_generics: bool,
82    ) -> Result<(), Error> {
83        T::fory_write_data_generic(&*self.lock().unwrap(), context, has_generics)
84    }
85
86    #[inline(always)]
87    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
88        // When called from Rc/Arc, just delegate to inner type's data serialization
89        let guard = self.lock().unwrap();
90        T::fory_write_data(&*guard, context)
91    }
92
93    #[inline(always)]
94    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
95        T::fory_write_type_info(context)
96    }
97
98    #[inline(always)]
99    fn fory_reserved_space() -> usize {
100        // Mutex is transparent, delegate to inner type
101        T::fory_reserved_space()
102    }
103
104    #[inline(always)]
105    fn fory_read(
106        context: &mut ReadContext,
107        read_ref_info: bool,
108        read_type_info: bool,
109    ) -> Result<Self, Error>
110    where
111        Self: Sized + ForyDefault,
112    {
113        Ok(Mutex::new(T::fory_read(
114            context,
115            read_ref_info,
116            read_type_info,
117        )?))
118    }
119
120    #[inline(always)]
121    fn fory_read_with_type_info(
122        context: &mut ReadContext,
123        read_ref_info: bool,
124        type_info: Rc<TypeInfo>,
125    ) -> Result<Self, Error>
126    where
127        Self: Sized + ForyDefault,
128    {
129        Ok(Mutex::new(T::fory_read_with_type_info(
130            context,
131            read_ref_info,
132            type_info,
133        )?))
134    }
135
136    #[inline(always)]
137    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
138        Ok(Mutex::new(T::fory_read_data(context)?))
139    }
140
141    #[inline(always)]
142    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
143        T::fory_read_type_info(context)
144    }
145
146    #[inline(always)]
147    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<u32, Error> {
148        T::fory_get_type_id(type_resolver)
149    }
150
151    #[inline(always)]
152    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
153        let guard = self.lock().unwrap();
154        (*guard).fory_type_id_dyn(type_resolver)
155    }
156
157    #[inline(always)]
158    fn fory_static_type_id() -> TypeId {
159        T::fory_static_type_id()
160    }
161
162    #[inline(always)]
163    fn fory_is_wrapper_type() -> bool
164    where
165        Self: Sized,
166    {
167        true
168    }
169
170    #[inline(always)]
171    fn as_any(&self) -> &dyn std::any::Any {
172        self
173    }
174}
175
176impl<T: ForyDefault> ForyDefault for Mutex<T> {
177    fn fory_default() -> Self {
178        Mutex::new(T::fory_default())
179    }
180}