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::context::{ReadContext, WriteContext};
45use crate::error::Error;
46use crate::resolver::RefMode;
47use crate::resolver::{TypeInfo, TypeResolver};
48use crate::serializer::{ForyDefault, Serializer};
49use crate::type_id::TypeId;
50use std::rc::Rc;
51use std::sync::Mutex;
52
53/// `Serializer` impl for `Mutex<T>`
54///
55/// Simply delegates to the serializer for `T`, allowing thread-safe interior mutable
56/// containers to be included in serialized graphs.
57impl<T: Serializer + ForyDefault> Serializer for Mutex<T> {
58    #[inline(always)]
59    fn fory_write(
60        &self,
61        context: &mut WriteContext,
62        ref_mode: RefMode,
63        write_type_info: bool,
64        has_generics: bool,
65    ) -> Result<(), Error> {
66        // Don't add ref tracking for Mutex itself, just delegate to inner type
67        // The inner type will handle its own ref tracking
68        let guard = self.lock().unwrap();
69        T::fory_write(&*guard, context, ref_mode, write_type_info, has_generics)
70    }
71
72    #[inline(always)]
73    fn fory_write_data_generic(
74        &self,
75        context: &mut WriteContext,
76        has_generics: bool,
77    ) -> Result<(), Error> {
78        T::fory_write_data_generic(&*self.lock().unwrap(), context, has_generics)
79    }
80
81    #[inline(always)]
82    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
83        // When called from Rc/Arc, just delegate to inner type's data serialization
84        let guard = self.lock().unwrap();
85        T::fory_write_data(&*guard, context)
86    }
87
88    #[inline(always)]
89    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
90        T::fory_write_type_info(context)
91    }
92
93    #[inline(always)]
94    fn fory_reserved_space() -> usize {
95        // Mutex is transparent, delegate to inner type
96        T::fory_reserved_space()
97    }
98
99    #[inline(always)]
100    fn fory_read(
101        context: &mut ReadContext,
102        ref_mode: RefMode,
103        read_type_info: bool,
104    ) -> Result<Self, Error>
105    where
106        Self: Sized + ForyDefault,
107    {
108        Ok(Mutex::new(T::fory_read(context, ref_mode, read_type_info)?))
109    }
110
111    #[inline(always)]
112    fn fory_read_with_type_info(
113        context: &mut ReadContext,
114        ref_mode: RefMode,
115        type_info: Rc<TypeInfo>,
116    ) -> Result<Self, Error>
117    where
118        Self: Sized + ForyDefault,
119    {
120        Ok(Mutex::new(T::fory_read_with_type_info(
121            context, ref_mode, type_info,
122        )?))
123    }
124
125    #[inline(always)]
126    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
127        Ok(Mutex::new(T::fory_read_data(context)?))
128    }
129
130    #[inline(always)]
131    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
132        T::fory_read_type_info(context)
133    }
134
135    #[inline(always)]
136    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<TypeId, Error> {
137        T::fory_get_type_id(type_resolver)
138    }
139
140    #[inline(always)]
141    fn fory_get_type_info(type_resolver: &TypeResolver) -> Result<Rc<TypeInfo>, Error> {
142        T::fory_get_type_info(type_resolver)
143    }
144
145    #[inline(always)]
146    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<TypeId, Error> {
147        let guard = self.lock().unwrap();
148        (*guard).fory_type_id_dyn(type_resolver)
149    }
150
151    #[inline(always)]
152    fn fory_static_type_id() -> TypeId {
153        T::fory_static_type_id()
154    }
155
156    #[inline(always)]
157    fn fory_is_wrapper_type() -> bool
158    where
159        Self: Sized,
160    {
161        true
162    }
163
164    #[inline(always)]
165    fn as_any(&self) -> &dyn std::any::Any {
166        self
167    }
168}
169
170impl<T: ForyDefault> ForyDefault for Mutex<T> {
171    fn fory_default() -> Self {
172        Mutex::new(T::fory_default())
173    }
174}