Skip to main content

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::{RefMode, 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        ref_mode: RefMode,
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(&*guard, context, ref_mode, write_type_info, has_generics)
69    }
70
71    #[inline(always)]
72    fn fory_write_data_generic(
73        &self,
74        context: &mut WriteContext,
75        has_generics: bool,
76    ) -> Result<(), Error> {
77        T::fory_write_data_generic(&*self.lock().unwrap(), context, has_generics)
78    }
79
80    #[inline(always)]
81    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
82        // When called from Rc/Arc, just delegate to inner type's data serialization
83        let guard = self.lock().unwrap();
84        T::fory_write_data(&*guard, context)
85    }
86
87    #[inline(always)]
88    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
89        T::fory_write_type_info(context)
90    }
91
92    #[inline(always)]
93    fn fory_reserved_space() -> usize {
94        // Mutex is transparent, delegate to inner type
95        T::fory_reserved_space()
96    }
97
98    #[inline(always)]
99    fn fory_read(
100        context: &mut ReadContext,
101        ref_mode: RefMode,
102        read_type_info: bool,
103    ) -> Result<Self, Error>
104    where
105        Self: Sized + ForyDefault,
106    {
107        Ok(Mutex::new(T::fory_read(context, ref_mode, read_type_info)?))
108    }
109
110    #[inline(always)]
111    fn fory_read_with_type_info(
112        context: &mut ReadContext,
113        ref_mode: RefMode,
114        type_info: Rc<TypeInfo>,
115    ) -> Result<Self, Error>
116    where
117        Self: Sized + ForyDefault,
118    {
119        Ok(Mutex::new(T::fory_read_with_type_info(
120            context, ref_mode, type_info,
121        )?))
122    }
123
124    #[inline(always)]
125    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
126        Ok(Mutex::new(T::fory_read_data(context)?))
127    }
128
129    #[inline(always)]
130    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
131        T::fory_read_type_info(context)
132    }
133
134    #[inline(always)]
135    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
136        T::fory_get_type_id(type_resolver)
137    }
138
139    #[inline(always)]
140    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
141        match type_resolver.get_type_info(&std::any::TypeId::of::<T>()) {
142            Ok(info) => Ok(info),
143            Err(e) => Err(Error::enhance_type_error::<T>(e)),
144        }
145    }
146
147    #[inline(always)]
148    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
149        let guard = self.lock().unwrap();
150        (*guard).fory_type_id_dyn(type_resolver)
151    }
152
153    #[inline(always)]
154    fn fory_static_type_id() -> TypeId {
155        T::fory_static_type_id()
156    }
157
158    #[inline(always)]
159    fn fory_is_wrapper_type() -> bool
160    where
161        Self: Sized,
162    {
163        true
164    }
165
166    #[inline(always)]
167    fn as_any(&self) -> &dyn std::any::Any {
168        self
169    }
170}
171
172impl<T: ForyDefault> ForyDefault for Mutex<T> {
173    fn fory_default() -> Self {
174        Mutex::new(T::fory_default())
175    }
176}