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}