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    fn fory_write(
58        &self,
59        context: &mut WriteContext,
60        write_ref_data: bool,
61        write_type_info: bool,
62        has_generics: bool,
63    ) -> Result<(), Error> {
64        // Don't add ref tracking for Mutex itself, just delegate to inner type
65        // The inner type will handle its own ref tracking
66        let guard = self.lock().unwrap();
67        T::fory_write(
68            &*guard,
69            context,
70            write_ref_data,
71            write_type_info,
72            has_generics,
73        )
74    }
75
76    fn fory_write_data_generic(
77        &self,
78        context: &mut WriteContext,
79        has_generics: bool,
80    ) -> Result<(), Error> {
81        T::fory_write_data_generic(&*self.lock().unwrap(), context, has_generics)
82    }
83
84    fn fory_write_data(&self, context: &mut WriteContext) -> Result<(), Error> {
85        // When called from Rc/Arc, just delegate to inner type's data serialization
86        let guard = self.lock().unwrap();
87        T::fory_write_data(&*guard, context)
88    }
89
90    fn fory_write_type_info(context: &mut WriteContext) -> Result<(), Error> {
91        T::fory_write_type_info(context)
92    }
93
94    fn fory_reserved_space() -> usize {
95        // Mutex is transparent, delegate to inner type
96        T::fory_reserved_space()
97    }
98
99    fn fory_read(
100        context: &mut ReadContext,
101        read_ref_info: bool,
102        read_type_info: bool,
103    ) -> Result<Self, Error>
104    where
105        Self: Sized + ForyDefault,
106    {
107        Ok(Mutex::new(T::fory_read(
108            context,
109            read_ref_info,
110            read_type_info,
111        )?))
112    }
113
114    fn fory_read_with_type_info(
115        context: &mut ReadContext,
116        read_ref_info: bool,
117        type_info: Rc<TypeInfo>,
118    ) -> Result<Self, Error>
119    where
120        Self: Sized + ForyDefault,
121    {
122        Ok(Mutex::new(T::fory_read_with_type_info(
123            context,
124            read_ref_info,
125            type_info,
126        )?))
127    }
128
129    fn fory_read_data(context: &mut ReadContext) -> Result<Self, Error> {
130        Ok(Mutex::new(T::fory_read_data(context)?))
131    }
132
133    fn fory_read_type_info(context: &mut ReadContext) -> Result<(), Error> {
134        T::fory_read_type_info(context)
135    }
136
137    fn fory_get_type_id(type_resolver: &TypeResolver) -> Result<u32, Error> {
138        T::fory_get_type_id(type_resolver)
139    }
140
141    fn fory_type_id_dyn(&self, type_resolver: &TypeResolver) -> Result<u32, Error> {
142        let guard = self.lock().unwrap();
143        (*guard).fory_type_id_dyn(type_resolver)
144    }
145
146    fn fory_static_type_id() -> TypeId {
147        T::fory_static_type_id()
148    }
149
150    fn as_any(&self) -> &dyn std::any::Any {
151        self
152    }
153}
154
155impl<T: ForyDefault> ForyDefault for Mutex<T> {
156    fn fory_default() -> Self {
157        Mutex::new(T::fory_default())
158    }
159}