1
1
// Take a look at the license at the top of the repository in the LICENSE file.
2
2
3
+ use heck:: ToShoutySnakeCase ;
3
4
use proc_macro2:: TokenStream ;
4
5
use proc_macro_error:: abort_call_site;
5
- use quote:: { quote, ToTokens } ;
6
+ use quote:: { format_ident , quote, ToTokens } ;
6
7
7
8
use crate :: utils:: { parse_optional_nested_meta_items, NestedMetaItem } ;
8
9
@@ -20,6 +21,18 @@ pub fn impl_object_subclass(input: &mut syn::ItemImpl) -> TokenStream {
20
21
..
21
22
} = input;
22
23
24
+ let self_ty_as_ident = match & * * self_ty {
25
+ syn:: Type :: Path ( syn:: TypePath { path, .. } ) => path. require_ident ( ) ,
26
+ _ => Err ( syn:: Error :: new (
27
+ syn:: spanned:: Spanned :: span ( self_ty) ,
28
+ "expected this path to be an identifier" ,
29
+ ) ) ,
30
+ } ;
31
+ let self_ty = match self_ty_as_ident {
32
+ Ok ( ident) => ident,
33
+ Err ( e) => return e. to_compile_error ( ) ,
34
+ } ;
35
+
23
36
let mut plugin_type = NestedMetaItem :: < syn:: Path > :: new ( "plugin_type" ) . value_required ( ) ;
24
37
let mut lazy_registration =
25
38
NestedMetaItem :: < syn:: LitBool > :: new ( "lazy_registration" ) . value_required ( ) ;
@@ -190,7 +203,7 @@ pub fn impl_object_subclass(input: &mut syn::ItemImpl) -> TokenStream {
190
203
// Registers the object subclass as a static type.
191
204
fn register_object_subclass_as_static (
192
205
crate_ident : & TokenStream ,
193
- self_ty : & syn:: Type ,
206
+ self_ty : & syn:: Ident ,
194
207
) -> TokenStream {
195
208
// registers the object subclass on first use (lazy registration).
196
209
quote ! {
@@ -212,7 +225,7 @@ fn register_object_subclass_as_static(
212
225
// An object subclass can be reregistered as a dynamic type.
213
226
fn register_object_subclass_as_dynamic (
214
227
crate_ident : & TokenStream ,
215
- self_ty : & syn:: Type ,
228
+ self_ty : & syn:: Ident ,
216
229
plugin_ty : TokenStream ,
217
230
lazy_registration : bool ,
218
231
) -> TokenStream {
@@ -222,27 +235,35 @@ fn register_object_subclass_as_dynamic(
222
235
// registers the object subclass as a dynamic type on the first use (lazy registration).
223
236
// a weak reference on the plugin is stored and will be used later on the first use of the object subclass.
224
237
// this implementation relies on a static storage of a weak reference on the plugin and of the GLib type to know if the object subclass has been registered.
238
+
239
+ // the registration status type.
240
+ let registration_status_type = format_ident ! ( "{}RegistrationStatus" , self_ty) ;
241
+ // name of the static variable to store the registration status.
242
+ let registration_status = format_ident ! (
243
+ "{}" ,
244
+ registration_status_type. to_string( ) . to_shouty_snake_case( )
245
+ ) ;
246
+
225
247
quote ! {
226
- impl #self_ty {
227
- /// Returns a mutable reference to the registration status: a tuple of the weak reference on the plugin and of the GLib type.
228
- /// This is safe because the mutable reference guarantees that no other threads are concurrently accessing the data.
229
- #[ inline]
230
- fn get_registration_status_ref_mut( ) -> & ' static mut Option <( <#plugin_ty as #crate_ident:: clone:: Downgrade >:: Weak , #crate_ident:: Type ) > {
231
- static mut REGISTRATION_STATUS : :: std:: sync:: Mutex <Option <( <#plugin_ty as #crate_ident:: clone:: Downgrade >:: Weak , #crate_ident:: Type ) >> = :: std:: sync:: Mutex :: new( None ) ;
232
- unsafe { REGISTRATION_STATUS . get_mut( ) . unwrap( ) }
233
- }
248
+ /// The registration status type: a tuple of the weak reference on the plugin and of the GLib type.
249
+ struct #registration_status_type( <#plugin_ty as #crate_ident:: clone:: Downgrade >:: Weak , #crate_ident:: Type ) ;
250
+ unsafe impl Send for #registration_status_type { }
234
251
252
+ /// The registration status protected by a mutex guarantees so that no other threads are concurrently accessing the data.
253
+ static #registration_status: :: std:: sync:: Mutex <Option <#registration_status_type>> = :: std:: sync:: Mutex :: new( None ) ;
254
+
255
+ impl #self_ty {
235
256
/// Registers the object subclass as a dynamic type within the plugin only once.
236
257
/// Plugin must have been used at least once.
237
258
/// Do nothing if plugin has never been used or if the object subclass is already registered as a dynamic type.
238
259
#[ inline]
239
260
fn register_type( ) {
240
- let registration_status_ref_mut = Self :: get_registration_status_ref_mut ( ) ;
241
- match registration_status_ref_mut {
261
+ let mut registration_status = #registration_status . lock ( ) . unwrap ( ) ;
262
+ match :: std :: ops :: DerefMut :: deref_mut ( & mut registration_status ) {
242
263
// plugin has never been used, so the object subclass cannot be registered as a dynamic type.
243
264
None => ( ) ,
244
265
// plugin has been used and the object subclass has not been registered yet, so registers it as a dynamic type.
245
- Some ( ( type_plugin, type_) ) if !type_. is_valid( ) => {
266
+ Some ( #registration_status_type ( type_plugin, type_) ) if !type_. is_valid( ) => {
246
267
* type_ = #crate_ident:: subclass:: register_dynamic_type:: <#plugin_ty, Self >( & ( type_plugin. upgrade( ) . unwrap( ) ) ) ;
247
268
} ,
248
269
// plugin has been used and the object subclass has already been registered as a dynamic type.
@@ -257,15 +278,15 @@ fn register_object_subclass_as_dynamic(
257
278
/// If plugin is reused (and has reloaded the implementation) and the object subclass has not been registered yet as a dynamic type, do nothing.
258
279
#[ inline]
259
280
pub fn on_implementation_load( type_plugin: & #plugin_ty) -> bool {
260
- let registration_status_ref_mut = Self :: get_registration_status_ref_mut ( ) ;
261
- match registration_status_ref_mut {
281
+ let mut registration_status = #registration_status . lock ( ) . unwrap ( ) ;
282
+ match :: std :: ops :: DerefMut :: deref_mut ( & mut registration_status ) {
262
283
// plugin has never been used (this is the first time), so postpones registration of the object subclass as a dynamic type on the first use.
263
284
None => {
264
- * registration_status_ref_mut = Some ( ( #crate_ident:: clone:: Downgrade :: downgrade( type_plugin) , #crate_ident:: Type :: INVALID ) ) ;
285
+ * registration_status = Some ( #registration_status_type ( #crate_ident:: clone:: Downgrade :: downgrade( type_plugin) , #crate_ident:: Type :: INVALID ) ) ;
265
286
true
266
287
} ,
267
288
// plugin has been used at least one time and the object subclass has been registered as a dynamic type at least one time, so re-registers it.
268
- Some ( ( _, type_) ) if type_. is_valid( ) => {
289
+ Some ( #registration_status_type ( _, type_) ) if type_. is_valid( ) => {
269
290
* type_ = #crate_ident:: subclass:: register_dynamic_type:: <#plugin_ty, Self >( type_plugin) ;
270
291
type_. is_valid( )
271
292
} ,
@@ -281,15 +302,15 @@ fn register_object_subclass_as_dynamic(
281
302
/// Else do nothing.
282
303
#[ inline]
283
304
pub fn on_implementation_unload( type_plugin_: & #plugin_ty) -> bool {
284
- let registration_status_ref_mut = Self :: get_registration_status_ref_mut ( ) ;
285
- match registration_status_ref_mut {
305
+ let mut registration_status = #registration_status . lock ( ) . unwrap ( ) ;
306
+ match :: std :: ops :: DerefMut :: deref_mut ( & mut registration_status ) {
286
307
// plugin has never been used, so unload implementation is unexpected.
287
308
None => false ,
288
309
// plugin has been used at least one time and the object subclass has been registered as a dynamic type at least one time.
289
- Some ( ( _, type_) ) if type_. is_valid( ) => true ,
310
+ Some ( #registration_status_type ( _, type_) ) if type_. is_valid( ) => true ,
290
311
// plugin has been used at least one time but the object subclass has not been registered yet as a dynamic type, so cancels the postponed registration.
291
312
Some ( _) => {
292
- * registration_status_ref_mut = None ;
313
+ * registration_status = None ;
293
314
true
294
315
}
295
316
}
@@ -298,6 +319,7 @@ fn register_object_subclass_as_dynamic(
298
319
}
299
320
} else {
300
321
// registers immediately the object subclass as a dynamic type.
322
+
301
323
quote ! {
302
324
impl #self_ty {
303
325
/// Do nothing as the object subclass has been registered on implementation load.
0 commit comments