interthread/
lib.rs

1
2
3
4//! # Intro
5//!
6//! This document covers the usage of the crate's macros, it does 
7//! not delve into the detailed logic of the generated code.
8//! 
9//! For a comprehensive understanding of the underlying
10//! concepts and implementation details of the Actor Model,  
11//! it's recommended to read the article  [Actors with Tokio](https://ryhl.io/blog/actors-with-tokio/)
12//! by Alice Ryhl ( also known as _Darksonn_ ) also a great 
13//! talk by the same author on the same subject if a more 
14//! interactive explanation is prefered 
15//! [Actors with Tokio – a lesson in ownership - Alice Ryhl](https://www.youtube.com/watch?v=fTXuGRP1ee4)
16//! (video).
17//! This article not only inspired the development of the 
18//! `interthread` crate but serves as foundation 
19//! for the Actor Model implementation logic in it. 
20
21
22//! ## What is an Actor ?
23//!
24//! Despite being a fundamental concept in concurrent programming,
25//! defining exactly what an actor is can be ambiguous.
26//! 
27//! - *Carl Hewitt*, often regarded as the father of the Actor Model,
28//! [The Actor Model](https://www.youtube.com/watch?v=7erJ1DV_Tlo) (video).
29//! 
30//! - Wikipidia [Actor Model](https://en.wikipedia.org/wiki/Actor_model)
31//!  
32//!
33//! a quote from [Actors with Tokio](https://ryhl.io/blog/actors-with-tokio/):
34//! 
35//! > "The basic idea behind an actor is to spawn a 
36//! self-contained task that performs some job independently
37//! of other parts of the program. Typically these actors
38//! communicate with the rest of the program through 
39//! the use of message passing channels. Since each actor 
40//! runs independently, programs designed using them are 
41//! naturally parallel."
42//! > - Alice Ryhl 
43//!
44//! ## What is the problem ?
45//! 
46//! To achieve parallel execution of individual objects 
47//! within the same program, it is challenging due 
48//! to the need for various types that are capable of 
49//! working across threads. The main difficulty 
50//! lies in the fact that as you introduce thread-related types,
51//! you can quickly lose sight of the main program 
52//! idea as the focus shifts to managing thread-related 
53//! concerns.
54//!
55//! It involves using constructs like threads, locks, channels,
56//! and other synchronization primitives. These additional 
57//! types and mechanisms introduce complexity and can obscure 
58//! the core logic of the program.
59//! 
60//! 
61//! ## Solution 
62//! 
63//! The [`actor`](./attr.actor.html) macro -  when applied to the 
64//! implementation block of a given "MyActor" object,
65//! generates additional Struct types  
66//! that enable communication between threads.
67//! 
68//! A notable outcome of applying this macro is the 
69//! creation of the `MyActorLive` struct ("ActorName" + "Live"),
70//! which acts as an interface/handle to the `MyActor` object.
71//! `MyActorLive` retains the exact same public method signatures
72//! as `MyActor`, allowing users to interact with the actor as if 
73//! they were directly working with the original object.
74//! 
75//! ### Examples
76//! 
77//! 
78//! Filename: Cargo.toml
79//! 
80//!```text
81//![dependencies]
82//!interthread = "3.1.0"
83//!oneshot     = "0.1.11" 
84//!```
85//! 
86//! Filename: main.rs
87//!```rust no_run
88//!pub struct MyActor {
89//!    value: i8,
90//!}
91//!
92//!#[interthread::actor] 
93//!impl MyActor {
94//!
95//!    pub fn new( v: i8 ) -> Self {
96//!       Self { value: v } 
97//!    }
98//!    pub fn increment(&mut self) {
99//!        self.value += 1;
100//!    }
101//!    pub fn add_number(&mut self, num: i8) -> i8 {
102//!        self.value += num;
103//!        self.value
104//!    }
105//!    pub fn get_value(&self) -> i8 {
106//!        self.value
107//!    }
108//!}
109//!
110//!fn main() {
111//!
112//!    let actor = MyActorLive::new(5);
113//!
114//!    let mut actor_a = actor.clone();
115//!    let mut actor_b = actor.clone();
116//!
117//!    let handle_a = std::thread::spawn( move || { 
118//!    actor_a.increment();
119//!    });
120//!
121//!    let handle_b = std::thread::spawn( move || {
122//!    actor_b.add_number(5);
123//!    });
124//!
125//!    let _ = handle_a.join();
126//!    let _ = handle_b.join();
127//!
128//!    assert_eq!(actor.get_value(), 11)
129//!}
130//!
131//! ```
132//! 
133//! An essential point to highlight is that when invoking 
134//! `MyActorLive::new`, not only does it return an instance 
135//! of `MyActorLive`, but it also spawns a new thread that 
136//! contains an instance of `MyActor` in it. 
137//! This introduces parallelism to the program.
138//! 
139//! The code generated by the [`actor`](./attr.actor.html) takes 
140//! care of the underlying message routing and synchronization, 
141//! allowing developers to rapidly prototype their application's
142//! core functionality. This fast sketching capability is
143//! particularly useful when exploring different design options, 
144//! experimenting with concurrency models, or implementing 
145//! proof-of-concept systems. Not to mention, the cases where 
146//! the importance of the program lies in the result of its work 
147//! rather than its execution.
148//!
149//! 
150//! # SDPL Framework
151//! 
152//! 
153//!  The code generated by the [`actor`](./attr.actor.html) macro 
154//! can be divided into four more or less important but distinct 
155//! parts: [`script`](#script) ,[`direct`](#direct), 
156//! [`play`](#play), [`live`](#live) .
157//! 
158//!  This categorization provides an intuitive 
159//! and memorable way to understand the different aspects 
160//! of the generated code.
161//! 
162//! Expanding the above example, uncomment the [`example`](./attr.example.html)
163//! placed above the `main` function, go to `examples/inter/main.rs` in your 
164//! root directory and find `MyActor` along with additional SDPL parts :
165//! 
166//! # `script`
167//! 
168//!  Think of script as a message type definition.
169//! 
170//!  The declaration of an `ActorName + Script` enum, which is 
171//! serving as a collection of variants that represent 
172//! different messages that may be sent across threads through a
173//! channel. 
174//! 
175//!  Each variant corresponds to a struct with fields
176//! that capture the input and/or output parameters of 
177//! the respective public methods of the Actor.
178//!  
179//! 
180//! ```rust no_run
181//! 
182//! pub enum MyActorScript {
183//!     Increment {},
184//!     AddNumber { num: i8, inter_send: oneshot::Sender<i8> },
185//!     GetValue { inter_send: oneshot::Sender<i8> },
186//! }
187//! 
188//! ```
189//! 
190//! > **Note**: Method `new` not included as a variant in the `script`. 
191//! 
192//! 
193//! # direct
194//! The implementation block of `script`struct, specifically 
195//! the `direct` method which allows 
196//! for direct invocation of the Actor's methods by mapping 
197//! the enum variants to the corresponding function calls.
198//! 
199//! 
200//!```rust no_run
201//!impl MyActorScript {
202//!    pub fn direct(self, actor: &mut MyActor) {
203//!        match self {
204//!            MyActorScript::Increment {} => {
205//!                actor.increment();
206//!            }
207//!            MyActorScript::AddNumber { num, inter_send } => {
208//!                inter_send
209//!                    .send(actor.add_number(num))
210//!                    .unwrap_or_else(|_error| {
211//!                        core::panic!(
212//!                            "'MyActorScript::AddNumber.direct'. Sending on a closed channel."
213//!                        )
214//!                    });
215//!            }
216//!            MyActorScript::GetValue { inter_send } => {
217//!                inter_send
218//!                    .send(actor.get_value())
219//!                    .unwrap_or_else(|_error| {
220//!                        core::panic!(
221//!                            "'MyActorScript::GetValue.direct'. Sending on a closed channel."
222//!                        )
223//!                    });
224//!            }
225//!        }
226//!    }
227//!}
228//!```
229//! 
230//! # play
231//! The implementation block of `script`struct, specifically 
232//! the `play` associated (static) method responsible for 
233//! continuously receiving `script` variants from 
234//! a dedicated channel and `direct`ing them.
235//! 
236//! Also this function serves as the home for the Actor itself.
237//! 
238//! 
239//!```rust no_run
240//!impl MyActorScript { 
241//!    pub fn play(receiver: std::sync::mpsc::Receiver<MyActorScript>, 
242//!               mut actor: MyActor) {
243//!        while let std::result::Result::Ok(msg) = receiver.recv() {
244//!            msg.direct(&mut actor);
245//!        }
246//!        eprintln!("MyActor the end ...");
247//!    }
248//!}
249//!``` 
250//! 
251//! When using the [`edit`](./attr.actor.html#edit) argument in the [`actor`](./attr.actor.html) 
252//! macro, such as 
253//! 
254//!```rust no_run
255//!#[interthread::actor(edit(script(imp(play))))]
256//!``` 
257//! 
258//! it allows for manual implementation of the `play` part, which 
259//! gives the flexibility to customize and modify 
260//! the behavior of the `play` to suit any requared logic.
261//! 
262//! 
263//! 
264//! # live
265//! A struct `ActorName + Live`, which serves as an interface/handler 
266//! replicating the public method signatures of the original Actor.
267//! 
268//! Invoking a method on a live instance, it's triggering the eventual 
269//! invocation of the corresponding method within the Actor. 
270//! 
271//! The special method of `live` method `new`  
272//! - initiates a new channel
273//! - initiates an instace of the Actor
274//! - spawns the `play` component in a separate thread 
275//! - returns an instance of `Self`
276//! 
277//! 
278//! ```rust no_run 
279//! 
280//!#[derive(Clone)]
281//!pub struct MyActorLive {
282//!    sender: std::sync::mpsc::Sender<MyActorScript>,
283//!}
284//!impl MyActorLive {
285//!    pub fn new(v: i8) -> Self {
286//!        let actor = MyActor::new(v);
287//!        let (sender, receiver) = std::sync::mpsc::channel();
288//!        std::thread::spawn(move || { MyActorScript::play(receiver, actor) });
289//!        Self { sender }
290//!    }
291//!    pub fn increment(&mut self) {
292//!        let msg = MyActorScript::Increment {};
293//!        let _ = self
294//!            .sender
295//!            .send(msg)
296//!            .expect("'MyActorLive::method.send'. Channel is closed!");
297//!    }
298//!    pub fn add_number(&mut self, num: i8) -> i8 {
299//!        let (inter_send, inter_recv) = oneshot::channel();
300//!        let msg = MyActorScript::AddNumber {
301//!            num,
302//!            inter_send,
303//!        };
304//!        let _ = self
305//!            .sender
306//!            .send(msg)
307//!            .expect("'MyActorLive::method.send'. Channel is closed!");
308//!        inter_recv
309//!            .recv()
310//!            .unwrap_or_else(|_error| {
311//!                core::panic!("'MyActor::add_number' from inter_recv. Channel is closed!")
312//!            })
313//!    }
314//!    pub fn get_value(&self) -> i8 {
315//!        let (inter_send, inter_recv) = oneshot::channel();
316//!        let msg = MyActorScript::GetValue {
317//!            inter_send,
318//!        };
319//!        let _ = self
320//!            .sender
321//!            .send(msg)
322//!            .expect("'MyActorLive::method.send'. Channel is closed!");
323//!        inter_recv
324//!            .recv()
325//!            .unwrap_or_else(|_error| {
326//!                core::panic!("'MyActor::get_value' from inter_recv. Channel is closed!")
327//!            })
328//!    }
329//!}
330//! 
331//! ```
332//! The methods of `live` type have same method signature
333//! as Actor's own methods 
334//! - initiate a `oneshot` channel
335//! - create a `msg` specific `script` variant
336//! - send the `msg` via `live`'s channel 
337//! - receive and return the output if any   
338//! 
339//! # Panics
340//! 
341//! The model will panic if an attempt is made to send or 
342//! receive on the channel after it has been dropped. 
343//! Generally, such issues are unlikely to occur, but 
344//! if the `interact` option is used, it introduces a 
345//! potential scenario for encountering this situation.
346//!  
347//! 
348//! # Macro Implicit Dependencies
349//!
350//! The [`actor`](./attr.actor.html) macro generates code
351//! that utilizes channels for communication. However, 
352//! the macro itself does not provide any channel implementations.
353//! Therefore, depending on the libraries used in your project, 
354//! you may need to import additional crates.
355//!
356//!### Crate Compatibility
357//!<table>
358//!  <thead>
359//!    <tr>
360//!      <th>lib</th>
361//!      <th><a href="https://docs.rs/oneshot">oneshot</a></th>
362//!      <th><a href="https://docs.rs/async-channel">async_channel</a></th>
363//!    </tr>
364//!  </thead>
365//!  <tbody>
366//!    <tr>
367//!      <td>std</td>
368//!      <td style="text-align: center;">&#10003;</td>
369//!      <td style="text-align: center;"><b>-</b></td>
370//!    </tr>
371//!    <tr>
372//!      <td><a href="https://crates.io/crates/smol">smol</a></td>
373//!      <td style="text-align: center;">&#10003;</td>
374//!      <td style="text-align: center;">&#10003;</td>
375//!    </tr>
376//!    <tr>
377//!      <td><a href="https://docs.rs/tokio">tokio</a></td>
378//!      <td style="text-align: center;"><b>-</b></td>
379//!      <td style="text-align: center;"><b>-</b></td>
380//!    </tr>
381//!    <tr>
382//!      <td><a href="https://crates.io/crates/async-std">async-std</a></td>
383//!      <td style="text-align: center;">&#10003;</td>
384//!      <td style="text-align: center;"><b>-</b></td>
385//!    </tr>
386//!  </tbody>
387//!</table>
388//!
389//! 
390//!>**Note:** The table shows the compatibility of 
391//!>the macro with different libraries, indicating whether 
392//!>the dependencies are needed (✔) or not. 
393//!>The macros will provide helpful messages indicating 
394//!>the necessary crate imports based on your project's dependencies.
395//!
396//! 
397//! Checkout `interthread` on [![GitHub](https://img.shields.io/badge/GitHub-%2312100E.svg?&style=plastic&logo=GitHub&logoColor=white)](https://github.com/NimonSour/interthread)
398//! 
399
400
401mod use_macro;
402mod write;
403mod file;
404mod check;
405mod error;
406mod parse;
407mod model;
408
409static INTERTHREAD: &'static str            = "interthread";
410static INTER_EXAMPLE_DIR_NAME: &'static str = "INTER_EXAMPLE_DIR_NAME";
411static INTER: &'static str                  = "inter";
412// static WEB_ACTOR: &'static str              = "web_actor";
413
414static ACTOR: &'static str                  = "actor";
415static FAMILY: &'static str                 = "family";
416
417static EXAMPLE: &'static str                = "example";
418static EXAMPLES: &'static str               = "examples";
419
420const RWLOCK: &str = "RwLock";
421const MUTEX: &str  = "Mutex";
422const ARC: &str    = "Arc";
423
424// vars
425static INTER_SEND: &'static str = "inter_send";
426static INTER_RECV: &'static str = "inter_recv";
427
428// Some of Attributes Arguments
429static EDIT: &'static str = "edit";
430static FILE: &'static str = "file";
431
432
433
434#[cfg(windows)]
435const LINE_ENDING: &'static str = "\r\n";
436#[cfg(not(windows))]
437const LINE_ENDING: &'static str = "\n";
438
439/// # Code transparency and exploration
440///  
441/// [`example`](./attr.example.html) simplifies exploring and interacting with 
442/// expanded macro-generated code. It generates example files with expanded 
443/// content of `interthread` macros, making it easy for developers to debug, test, and experiment.
444/// 
445/// Consider a macro [`actor`](./attr.actor.html)  inside the project 
446/// in `src/my_file.rs`.
447/// 
448///Filename: my_file.rs 
449///```rust no_run
450/// 
451///pub struct MyActor;
452///
453/// // you can have "example" macro in the same file
454/// // #[interthread::example(path="src/my_file.rs")]
455///
456///#[interthread::actor]
457///impl MyActor {
458///    pub fn new(value: u32) -> Self {Self}
459///}
460///
461///```
462/// 
463///Filename: main.rs 
464///```rust no_run
465///#[interthread::example(path="src/my_file.rs")]
466///fn main(){
467///}
468///
469///```
470/// 
471/// The macro will create and write to `examples/inter/my_file.rs`
472/// the content of `src/my_file.rs` with the 
473/// [`actor`](./attr.actor.html) macro expanded.
474/// 
475/// 
476///```text
477///my_project/
478///├── src/
479///│  ├── my_file.rs      <---  macro "actor" 
480///|  |
481///│  └── main.rs         <---  macro "example" 
482///|
483///├── examples/          
484///   ├── ...
485///   └── inter/      
486///      ├── my_file.rs   <--- expanded "src/my_file.rs"  
487///```
488///
489/// When specifying the `main` argument 
490/// in the `example` macro. It generates two files within 
491/// the `examples/inter` directory: the expanded code file 
492/// and an additional `main.rs` file. 
493///
494///```rust no_run
495///#[example(main,path="my_file.rs")]
496///```
497///
498/// This option is particularly useful for debugging and experimentation. 
499/// It allows developers to quickly run and interact with the generated code by executing:
500///
501///```terminal
502///$ cargo run --example inter
503///```
504///
505/// The expanded code file will be located at 
506/// `examples/inter/my_file.rs`, while the `main.rs` file 
507/// serves as an entry point for running the example.
508/// 
509/// ## Configuration Options  
510///```text 
511/// 
512///#[interthread::example( 
513///
514///        main | mod *
515/// 
516///        path = "path/to/file.rs"  
517///
518///        expand(actor,family) *
519/// )]
520/// 
521/// * - default   
522/// 
523///```
524/// 
525/// # Arguments
526/// 
527/// - [`path`](#path)
528/// 
529/// - [`expand`](#expand) (default)
530/// 
531/// # path
532/// 
533/// The `path` argument is a required parameter of the [`example`](./attr.example.html) macro.
534/// It expects the path to the file that needs to be expanded.
535/// 
536/// This argument is essential as it specifies the target file 
537/// for code expansion.
538/// 
539/// [`example`](./attr.example.html) macro can be 
540/// placed on any item in any file within your `src` directory.
541/// 
542///  
543/// # expand
544/// 
545/// This argument allows the user to specify which 
546/// `interthread` macros to expand. 
547/// 
548/// By default, the value of `expand` includes 
549/// the [`actor`](./attr.actor.html) and 
550/// [`family`](./attr.family.html) macros.
551/// 
552/// For example, if you want to expand only the
553/// [`actor`](./attr.actor.html) macro in generated 
554/// example code, you can use the following attribute:
555/// 
556/// ```rust no_run
557/// #[example(path="my_file.rs",expand(actor))]
558/// ```
559/// This will generate an example code file that includes 
560/// the expanded code of the [`actor`](./attr.actor.html) macro,
561/// while excluding other macros like 
562/// [`family`](./attr.family.html).
563/// 
564 
565
566#[proc_macro_error::proc_macro_error]
567#[proc_macro_attribute]
568pub fn example( attr: proc_macro::TokenStream, _item: proc_macro::TokenStream ) -> proc_macro::TokenStream {
569
570    let nested  = syn::parse_macro_input!(attr with syn::punctuated::Punctuated::<syn::Meta,syn::Token![,]>::parse_terminated); 
571    let mut eaa   = model::attribute::ExampleAttributeArguments::from(nested);
572
573    let (file, lib)  = file::expand_macros(&eaa.get_path(),&eaa.expand);
574
575    let some_lib = if eaa.main { Some(lib)} else { None };
576
577    let path = write::example_show(file, &eaa.get_path(), some_lib );
578
579    let msg = format!("The file has been SUCCESSFULLY created at {}",path.to_string_lossy());
580    let note  = "To avoid potential issues and improve maintainability, it is recommended to comment out the macro after its successful execution. To proceed, please comment out the macro and re-run the compilation.";
581    
582    proc_macro_error::abort!( proc_macro2::Span::call_site(),msg; note = note);
583    
584}
585
586
587/// ## Evolves a regular object into an actor
588/// 
589/// The macro is placed upon an implement block of an object
590/// (`struct` or `enum`),
591/// which has a public or restricted method named `new` returning  `Self`.
592///
593/// In case if the initialization could potentially fail, 
594/// the method can be named `try_new` 
595/// and return `Option<Self>` or `Result<Self>`.
596/// 
597/// The macro will copy method signatures from all 
598/// public methods with receivers `&self` or `&mut self`
599/// and static methods.
600/// 
601/// The model is primarily designed to work for public methods with 
602/// borrowed receivers (e.g., `&self` or `&mut self`) however
603/// `Self`-consuming receiver (e.g., `self`) can be incorporated
604/// see [`What Does a Self-Consuming Method Mean for the Model`](#self-consuming-methods)
605/// 
606/// If only a subset of methods is required to be 
607/// accessible across threads, split the `impl` block 
608/// into two parts. By applying the macro to a specific block, 
609/// the macro will only consider the methods within that block, also see options
610/// [`include-exclude`](#include-exclude).
611/// 
612/// ## Configuration Options
613///```text 
614/// 
615///#[interthread::actor( 
616///    
617///    channel = 0 * 
618///              n (usize)
619///
620///        lib = "std" *
621///              "smol"
622///              "tokio"
623///              "async_std"
624///
625///        edit( 
626///             script(..)
627///             live(..)
628///            ) 
629///
630///        file = "path/to/current/file.rs"
631///        
632///        name = "" 
633///
634///        show
635///       
636///       include | exclude  
637///        
638///       debut
639/// 
640///    interact
641///)]
642///
643///*  -  default 
644///
645///
646///```
647///  
648/// # Arguments
649///  
650///
651/// - [`channel`](#channel)
652/// - [`lib`](#lib) 
653/// - [`edit`](#edit)
654/// - [`file`](#file)
655/// - [`name`](#name)
656/// - [`show`](#show)
657/// - [`include|exclude`](#include|exclude)
658/// - [`debut`](#debut)
659/// - [`interact`](#interact)
660///
661/// 
662/// 
663/// # channel
664///
665/// The `channel` argument specifies the type of channel. 
666///   
667/// - `0`  (default)
668/// - [`usize`] ( buffer size)
669/// 
670/// The two macros
671/// ```rust no_run
672/// #[actor]
673/// ```
674/// and
675/// ```rust no_run
676/// #[actor(channel=0)]
677/// ```
678/// are in fact identical, both specifying same unbounded channel.
679/// 
680/// When specifying an [`usize`] value for the `channel` argument 
681/// in the [`actor`](./attr.actor.html) macro, such as 
682/// ```rust no_run
683/// #[actor(channel=4)]
684/// ```
685/// the actor will use a bounded channel with a buffer size of 4.
686/// This means that the channel can hold up to 4 messages in its 
687/// buffer before blocking/suspending the sender.
688///
689/// Using a bounded channel with a specific buffer size allows 
690/// for control over the memory usage and backpressure behavior 
691/// of the model. When the buffer is full, any further attempts 
692/// to send messages will block/suspend until there is available space. 
693/// This provides a natural form of backpressure, allowing the 
694/// sender to slow down or pause message production when the 
695/// buffer is near capacity.
696/// 
697/// # lib
698///
699/// The `lib` argument specifies the 'async' library to use.
700///
701/// - `"std"` (default)
702/// - `"smol"`
703/// - `"tokio"`
704/// - `"async_std"`
705///
706///## Examples
707///```rust no_run
708///use interthread::actor;
709///
710///struct MyActor;
711///
712///#[actor(channel=10, lib ="tokio")]
713///impl MyActor{
714///    pub fn new() -> Self{Self}
715///}
716///#[tokio::main]
717///async fn main(){
718///    let my_act = MyActorLive::new();
719///}
720///```
721/// 
722/// # edit
723///
724/// The `edit` argument specifies the available editing options.
725/// When using this argument, the macro expansion will 
726/// **exclude** the code related to `edit` options 
727/// allowing the user to manually implement and 
728/// customize those parts according to their specific needs.
729/// 
730/// 
731/// The SDPL Model encompasses two main structs, namely `ActorScript` and `ActorLive`.
732/// Within the `edit` statement, these are referenced as `script` 
733/// and `live` respectively.
734/// 
735/// Each struct comprises three distinct sections: 
736/// - `def` - definition
737/// - `imp` - implementation block
738/// - `trt` - implemented traits
739///
740/// ```rust no_run
741/// edit(
742///     script(
743///         def,     // <- script definition
744///         imp(..), // <- list of methods in impl block
745///         trt(..)  // <- list of traits
746///     ),
747///     
748///     live(
749///         def,     // <- live definition
750///         imp(..), // <- list of methods in impl block
751///         trt(..)  // <- list of traits
752///     )
753/// )
754/// ```
755/// 
756/// So this option instructs the macro to:
757/// 
758/// - Exclude specified sections of code from the generated model.
759/// 
760/// Examples:
761/// - `edit(script)`: Excludes the entire Script enum.
762/// - `edit(live(imp))`: Excludes the entire implementation block of the Live struct.
763/// - `edit(live(def, imp(new)))`: Excludes both the definition of the Live struct and the method 'new.'
764/// - `edit(script(imp(play)), live(imp(new)))`: Excludes the 'play' method from the Script enum and the 'new' method from the Live struct.
765/// 
766/// Exclusion of code becomes necessary when the user has already 
767/// customized specific sections of the model. 
768/// To facilitate the exclusion of parts from the generated 
769/// model and enable printing them to the file for further 
770/// user customization, consider the [`file`](#file) option,
771/// which works in conjunction with the `edit` option.
772/// 
773/// # file
774/// This argument is designed to address proc macro file blindness. It requires 
775/// a string path to the current file as its value. Additionally, within the `edit` argument,
776/// one can use the keyword `file` to specify which portion of the excluded code should be written
777/// to the current module, providing the user with a starting point for customization.
778///  
779///  
780/// ## Examples
781/// 
782/// Filename: main.rs
783/// 
784///```rust no_run
785///pub struct MyActor(u8);
786///
787///#[interthread::actor(
788///    file="src/main.rs",
789///    edit(live(imp( file(increment) )))
790///)]  
791///
792///impl MyActor {
793///
794///    pub fn new() -> Self {Self(0)}
795///
796///    pub fn increment(&mut self){
797///        self.0 += 1;
798///    }
799///}
800///```
801/// This is the output after saving:
802/// 
803/// ```rust no_run
804///
805///pub struct MyActor(u8);
806///
807///#[interthread::actor(
808///    file="src/main.rs",
809///    edit(live(imp(increment)))
810///)]  
811///
812///impl MyActor {
813///
814///    pub fn new() -> Self {Self(0)}
815///
816///    pub fn increment(&mut self){
817///        self.0 += 1;
818///    }
819///}
820///
821/// //++++++++++++++++++[ Interthread  Write to File ]+++++++++++++++++//
822/// // Object Name   : MyActor  
823/// // Initiated By  : #[interthread::actor(file="src/main.rs",edit(live(imp(file(increment)))))]  
824/// 
825/// 
826/// impl MyActorLive {
827///     pub fn increment(&mut self) {
828///         let msg = MyActorScript::Increment {};
829///         let _ = self
830///             .sender
831///             .send(msg)
832///             .expect("'MyActorLive::method.send'. Channel is closed!");
833///     }
834/// }
835/// 
836/// // *///.............[ Interthread  End of Write  ].................//
837///
838/// ```
839/// 
840/// To specify the part of your model that should be written to 
841/// the file, simply enclose it within `file(..)` inside the `edit` 
842/// argument. Once the desired model parts are written, 
843/// the macro will automatically clean the `file` arguments, 
844/// adjusting itself to the correct state.
845/// 
846/// 
847/// Attempting to nest `file` arguments like: 
848/// ```rust no_run
849/// edit( file( script( file( def))))
850/// ```
851/// will result in an error.
852/// 
853/// 
854/// A special case of the `edit` and `file` conjunction, 
855/// using `edit(file)` results in the macro being replaced with 
856/// the generated code on the file.
857/// 
858/// 
859/// 
860///  > **Note:** While it is possible to have multiple actor macros
861/// within the same module, only one of the macro can have `file` 
862/// active arguments (`file` within `edit`) at a time.
863/// 
864/// 
865/// # name
866/// 
867/// The `name` attribute allows developers to provide a 
868/// custom name for `actor`, overriding the default 
869/// naming conventions of the crate. This can be useful 
870/// when there are naming conflicts or when a specific 
871/// naming scheme is desired.  
872/// 
873/// - "" (default): No name specified
874///
875/// ## Examples
876///```rust no_run
877///use interthread::actor;
878/// 
879///pub struct MyActor;
880/// 
881///#[actor(name="OtherActor")]
882///impl MyActor {
883///
884///   pub fn new() -> Self {Self}
885///}
886///fn main () {
887///   let other_act = OtherActorLive::new();
888///}
889///```
890/// 
891/// 
892/// # show 
893/// 
894/// The `show` option is particularly useful for users who are just starting to 
895/// work with this crate. When enabled, the model will generate doc comments 
896/// for every block of code it produces, containing the code produce, with the 
897/// exception of traits, which are simply listed.
898/// 
899/// Your text editor handles the rest.
900/// 
901/// By default, the model carries over the user's documentation comments from 
902/// the actor object methods. 
903/// Enabling `show` will add additional information, detailing the exact 
904/// code generated by the model.
905/// Try hovering over `AaLive` and its `new` method to see the generated code.
906/// 
907///  ## Examples
908///```rust no_run
909///use interthread::actor;
910///pub struct Aa;
911///  
912///#[actor(show)]
913///impl Aa {
914///    /// This is my comment
915///    /// Creates a new instance of AaLive.
916///    pub fn new() -> Self { Self{} }
917/// 
918///}
919///
920///fn main() {    
921///    let bb = AaLive::new(); 
922///}
923///
924///```
925/// Disable `show` to avoid performance overhead and excessive code generation, 
926/// when the option is no longer needed.
927/// 
928///  
929/// # include-exclude
930/// The include and exclude options are mutually exclusive filters that control 
931/// which methods are included in the generated model. Only one of these 
932/// options can be used at a time.
933/// 
934/// Usage
935/// 
936/// - include: Specifies the methods to include in the generated model.
937/// - exclude: Specifies the methods to exclude from the generated model.
938/// 
939/// For a given list of actor's methods `[a, b, c, d]`:
940/// 
941/// - Using `include(a)` will generate a model that only includes the method `a`.
942/// - Using `exclude(a,b)` will generate a model that includes the methods `c`, and `d`.
943/// 
944/// ```rust no_run
945/// #[interthread::actor( exclude(foo,bar))]
946/// ```
947/// 
948/// # debut
949/// 
950/// The generated code is designed to 
951/// compile successfully on Rust versions as early as 1.63.0.
952/// 
953/// When declared `debut`, the following additions and implementations 
954/// are generated:
955/// 
956/// 
957/// Within the [`live`](index.html#live) struct definition, the following
958/// fields are generated:
959/// 
960/// - `pub debut: std::time::SystemTime`
961/// - `pub name: String`
962/// 
963/// The following traits are implemented for the [`live`](index.html#live) struct:
964/// 
965/// - `PartialEq`
966/// - `PartialOrd`
967/// - `Eq`
968/// - `Ord`
969/// 
970/// These traits allow for equality and ordering 
971/// comparisons based on the `debut`value.
972/// The `name` field is provided for user needs only and is not 
973/// taken into account when performing comparisons. 
974/// It serves as a descriptive attribute or label 
975/// associated with each instance of the live struct.
976/// 
977/// In the [`script`](index.html#script) struct implementation block, which 
978/// encapsulates the functionality of the model,
979/// a static method named `debut` is generated. This 
980/// method returns the current system time and is commonly 
981/// used to set the `debut` field when initializing 
982/// instances of the [`live`](index.html#live) struct.
983/// 
984/// 
985/// Use macro [`example`](./attr.example.html) to see the generated code.
986/// 
987/// 
988/// ## Examples
989///  
990///```rust no_run
991///use std::thread::spawn;
992///pub struct MyActor ;
993///
994///#[interthread::actor( debut )] 
995///impl MyActor {
996///    pub fn new() -> Self { Self{} } 
997///}
998///fn main() {
999///
1000///    let actor_1 = MyActorLive::new();
1001///
1002///    let handle_2 = spawn( move || { 
1003///        MyActorLive::new()
1004///    });
1005///    let actor_2 = handle_2.join().unwrap();
1006///
1007///    let handle_3 = spawn( move || {
1008///        MyActorLive::new()
1009///    });
1010///    let actor_3 = handle_3.join().unwrap();
1011///    
1012///    // they are the same type objects
1013///    // but serving differrent threads
1014///    // different actors !   
1015///    assert!(actor_1 != actor_2);
1016///    assert!(actor_2 != actor_3);
1017///    assert!(actor_3 != actor_1);
1018///
1019///    // since we know the order of invocation
1020///    // we correctly presume
1021///    assert_eq!(actor_1 > actor_2, true );
1022///    assert_eq!(actor_2 > actor_3, true );
1023///    assert_eq!(actor_3 < actor_1, true );
1024///
1025///    // but if we check the order by `debute` value
1026///    assert_eq!(actor_1.debut < actor_2.debut, true );
1027///    assert_eq!(actor_2.debut < actor_3.debut, true );
1028///    assert_eq!(actor_3.debut > actor_1.debut, true );
1029///    
1030///    // This is because the 'debut' 
1031///    // is a time record of initiation
1032///    // Charles S Chaplin (1889)
1033///    // Keanu Reeves      (1964)
1034///
1035///
1036///    // we can count `live` instances for 
1037///    // every model
1038///    use std::sync::Arc;
1039///    let mut a11 = actor_1.clone();
1040///    let mut a12 = actor_1.clone();
1041///
1042///    let mut a31 = actor_3.clone();
1043///
1044///    assert_eq!(Arc::strong_count(&actor_1.debut), 3 );
1045///    assert_eq!(Arc::strong_count(&actor_2.debut), 1 );
1046///    assert_eq!(Arc::strong_count(&actor_3.debut), 2 );
1047///            
1048///
1049///    // or use getter `count`                 
1050///    assert_eq!(actor_1.inter_get_count(), 3 );
1051///    assert_eq!(actor_2.inter_get_count(), 1 );
1052///    assert_eq!(actor_3.inter_get_count(), 2 );
1053///    
1054///
1055///    use std::time::SystemTime;
1056///
1057///    // getter `debut` to get its timestamp   
1058///    let _debut1: SystemTime = actor_1.inter_get_debut();
1059///
1060///            
1061///    // the name field is not taken 
1062///    // into account when comparison is
1063///    // perfomed       
1064///    assert!( a11 == a12);
1065///    assert!( a11 != a31);
1066///
1067///    a11.name = String::from("Alice");
1068///    a12.name = String::from("Bob");
1069///
1070///    a31.name = String::from("Alice");
1071///
1072///    assert_eq!(a11 == a12, true );
1073///    assert_eq!(a11 != a31, true );
1074///
1075///    // setter `name` accepts any ToString  
1076///    a11.inter_set_name('t');
1077///    a12.inter_set_name(84u32);
1078///    a31.inter_set_name(3.14159);
1079///
1080///    // getter `name`                      
1081///    assert_eq!(a11.inter_get_name(), "t" );
1082///    assert_eq!(a12.inter_get_name(), "84" );
1083///    assert_eq!(a31.inter_get_name(), "3.14159" );
1084///
1085///}
1086///``` 
1087/// 
1088/// 
1089/// 
1090/// 
1091/// Using `debut` will generate fore additional
1092///methods in `live` implement block:
1093/// 
1094/// 1. `inter_set_name(s: ToString)`: Sets the value of the 
1095/// name field.
1096/// 2. `inter_get_name() -> &str`: Retrieves the value of the 
1097/// name field.
1098/// 3. `inter_get_debut() -> std::time::SystemTime`: Retrieves
1099/// the value of the debut field, which represents a timestamp.
1100/// 4. `inter_get_count() -> usize`: Provides the strong 
1101/// reference count for the debut field.
1102///  
1103///This convention allows 
1104///- easy identification in text editor methods that 
1105///solely manipulate the internal state of the live struct and/or 
1106///methods that are added by the `interthread` macros
1107///- it mitigates the risk of potential naming conflicts in case if there
1108///is or will be a custom method `get_name`
1109///-  helps the macro  identify methods that are intended 
1110///to be used within its context (see [`interact`](#interact))
1111///
1112/// # interact
1113/// 
1114/// The `interact` option is designed to provide the model with 
1115/// comprehensive non-blocking functionality, along with convenient 
1116/// internal getter calls to access the state of the `live` instance via
1117/// so called `inter variables` in actor methods.
1118/// 
1119/// ### Rules and Definitions
1120/// 
1121/// 1. The interact variables should be prefixed with `inter_`.
1122/// 2. Special interact variables are `inter_send` and `inter_recv`.
1123/// 3. Declaring an `inter_variable_name : Type`, within actor method
1124/// arguments implies that the `live` instance has a method 
1125/// `fn inter_get_variable_name(&self) -> Type` which takes no arguments 
1126/// and returns the `Type`. Exceptions to this rule apply for special 
1127/// interact variables.
1128/// 4. If the actor method returns a type, accessing special interact variables
1129/// is not allowed. 
1130/// 5. Only one end of special interact variables can be accessed at a time.
1131///  
1132/// 
1133/// 
1134/// The primary purpose of `interact` is to leverage its oneshot `inter_send` 
1135/// and `inter_recv` ends. This allows for
1136/// a form of non-blocking behavior: one end of the channel will be directly 
1137/// sent into the respective method, while the other end will be returned 
1138/// from the live instance method. 
1139/// 
1140/// 
1141/// ## Examples
1142/// ```rust no_run
1143/// 
1144///pub struct MyActor;
1145///
1146///// opt `interact`
1147///#[interthread::actor( interact )] 
1148///impl MyActor {
1149///
1150///    pub fn new() -> Self { Self{} } 
1151///
1152///    // oneshot channel can be accessed 
1153///    // in methods that do not return 
1154///    pub fn heavy_work(&self, inter_send: oneshot::Sender<u8>){
1155///
1156///        std::thread::spawn(move||{
1157///            // do some havy computation
1158///            let _ = inter_send.send(5);
1159///        });
1160///    }
1161///}
1162///
1163///fn main () {
1164///
1165///    let actor = MyActorLive::new();
1166/// 
1167///    // the signature is different
1168///    let recv: oneshot::Receiver<u8> = actor.heavy_work(); 
1169///    let int = recv.recv().unwrap();
1170///
1171///    assert_eq!(5u8, int);
1172///}
1173/// 
1174/// ``` 
1175///  
1176/// While a method that does not return a type (see original `heavy_work`) 
1177/// typically does not require a oneshot channel, the 
1178/// model will accommodate the user's request by instantiating 
1179/// a channel pair. 
1180/// 
1181///```rust no_run
1182/// 
1183///pub fn heavy_work(&self) -> oneshot::Receiver<u8> {
1184///    let (inter_send, inter_recv) = oneshot::channel::<u8>();
1185///    let msg = MyActorScript::HeavyWork {
1186///        input: (inter_send),
1187///    };
1188///    let _ = self
1189///        .sender
1190///        .send(msg)
1191///        .expect("'MyActorLive::method.send'. Channel is closed!");
1192///    inter_recv
1193///}
1194///``` 
1195/// 
1196/// 
1197/// Also `interact` will detect interact variables in actor methods 
1198/// and subsequently call required getters within respective 
1199/// method of the `live` instance.
1200/// 
1201/// ## Examples
1202/// ```rust no_run
1203/// pub struct MyActor(String);
1204///
1205/// #[interthread::actor(debut, interact )] 
1206/// impl MyActor {
1207///
1208///     pub fn new() -> Self { Self("".to_string()) } 
1209///
1210///     // We know there is a getter `inter_get_name`
1211///     // Using argument `inter_name` we imply
1212///     // we want the return type of that getter
1213///     pub fn set_value(&mut self, inter_name: String){
1214///         self.0 = inter_name;
1215///     }
1216///     pub fn get_value(&self) -> String {
1217///         self.0.clone()
1218///     }
1219/// }
1220///
1221/// fn main () {
1222///
1223///     let mut actor = MyActorLive::new();
1224///
1225///     // Setting name for `live` instance
1226///     actor.inter_set_name("cloud");
1227///
1228///     // Setting actor's value now
1229///     // Note the signature, it's not the same  
1230///     actor.set_value();
1231///
1232///     assert_eq!("cloud".to_string(), actor.get_value());
1233/// }
1234/// ```
1235/// 
1236/// 
1237/// Here is how `live` instance method `set_value` will look like:
1238/// 
1239/// 
1240/// ```rust no_run
1241/// 
1242/// pub fn set_value(&mut self) {
1243///     let inter_name = self.inter_get_name();
1244///     let msg = MyActorScript::SetValue {
1245///         input: inter_name,
1246///     };
1247///     let _ = self
1248///         .sender
1249///         .send(msg)
1250///         .expect("'MyActorLive::method.send'. Channel is closed!");
1251/// }
1252/// 
1253/// ```
1254/// 
1255/// 
1256/// The signature has changed; it no longer takes arguments, as the 
1257/// getter call is happening inside providing the required type. 
1258/// It will work for any custom getter as long as it adheres to rule 3.
1259/// 
1260/// 
1261/// 
1262/// # Self Consuming Methods
1263/// 
1264/// For every method in an `Actor` object that consumes `Actor`, the model generates
1265/// a corresponding method in the `ActorLive` interface object that consumes both itself and the associated `Actor`. 
1266/// 
1267/// However, this design introduces challenges. The model inherently allows 
1268/// multiple `ActorLive` instances to send messages to a single `Actor` instance 
1269/// running in a separate thread. When an `ActorLive` instance consumes itself and 
1270/// its associated `Actor`, it effectively leaves other `ActorLive` instances without 
1271/// a functional `Actor`, disrupting the model operation.
1272/// 
1273/// To safely implement such self-consuming methods, the following conditions must be met:
1274/// 
1275/// ### Safety Conditions for Self-Consuming Methods
1276/// 
1277/// 1. **Enable the `debut` Option**
1278///    The model must have the `debut` option enabled (e.g., ```interthread::actor(debut)```), 
1279///    which allows it to track the number of active `ActorLive` instances.
1280/// 
1281/// 2. **Return a Valid Result Type**
1282///    Self-consuming methods must return one of the following types:
1283///    - `Option<T>`
1284///    - `Result<T, String>`
1285///    - `Result<T, &'static str>`
1286/// 
1287///    This requirement enables the model to inject a reference count check for `ActorLive`. 
1288///    If there are multiple active `ActorLive` instances, the method will return `Option::None` 
1289///    or `Result::Err`, indicating that the operation cannot proceed safely.
1290/// 
1291/// ### Limitations for Non-Compliant Methods
1292/// 
1293/// If a self-consuming method deviates from the above rules, the model enforces the following restrictions:
1294/// 
1295/// 1. **No Cloning**
1296///    The model will disallow the `Clone` trait for `ActorLive` object.
1297/// 
1298/// 2. **Private Visibility**
1299///    Self-consuming methods will be restricted to private visibility, making them inaccessible outside the module. 
1300/// 
1301/// ## Examples
1302/// 
1303/// Some examples of compliant self-consuming methods:
1304/// 
1305/// ```rust no_run
1306/// pub fn method(self, args, ...) -> Option<T>;
1307/// 
1308/// pub fn method(self, args, ...) -> Result<T, String>;
1309/// 
1310/// pub fn method(self, args, ...) -> Result<T, &'static str>;
1311/// ```
1312/// 
1313/// These examples illustrate the required return types and demonstrate how 
1314/// `self`-consuming methods can be safely integrated into the actor model.
1315
1316#[proc_macro_error::proc_macro_error]
1317#[proc_macro_attribute]
1318pub fn actor( attr: proc_macro::TokenStream, item: proc_macro::TokenStream ) -> proc_macro::TokenStream {
1319    
1320    let item_impl = syn::parse_macro_input!(item as syn::ItemImpl);
1321
1322    let nested  = syn::parse_macro_input!(attr with syn::punctuated::Punctuated::<syn::Meta,syn::Token![,]>::parse_terminated); 
1323    let mut aaa = model::attribute::ActorAttributeArguments::from(nested, crate::model::Mac::Actor);
1324    aaa.cross_check();
1325
1326    check::channels_import( &aaa.lib );
1327
1328    let edit_attr = aaa.edit.attr.clone();
1329    let mut model_sdpl = crate::model::generate_model( aaa, &item_impl);
1330    let (code,edit_sdpl) = model_sdpl.get_code_edit();
1331    if let Some( edit_attr ) = edit_attr {
1332
1333        parse::edit_write( &edit_attr, &item_impl, edit_sdpl);
1334    }
1335
1336    quote::quote!{
1337        #item_impl
1338        #code
1339    }.into()
1340
1341}
1342
1343
1344
1345/// ## A Wrapper for Managing Parallel ActorLive Instances
1346/// 
1347/// The `family` macro is designed as a convenient wrapper for initializing a 
1348/// set of `ActorLive` instances that operate in parallel, all serving the same Actor. 
1349/// The core idea behind the `family` concept can be summarized as `Exclusive Access to the Actor`.
1350/// 
1351/// 
1352/// ## Configuration Options
1353/// The `family` macro provides the same configuration options as the `actor` macro, 
1354/// ( with few exceptions ) and are inherited by `actor`'s declared within its body (e.g., `actor(first_name = "User", ...)`) which behaves exactly like the standalone `actor` macro. It allows defining individual `actor`s within the `family`. 
1355/// 
1356/// Options not explicitly specified in the `actor` configuration will be inherited from the `family` macro. For example, if `channel` is defined in family but omitted in `actor`, the channel value from `family` will be applied to the `actor`.
1357/// 
1358/// If the same-named options are present in both `family` and `actor`, they are treated independently.
1359/// 
1360/// ```text
1361/// #[interthread::family( 
1362///     
1363///   ~ channel = 0 * 
1364///               n (usize)
1365/// 
1366///         lib = std *
1367///               tokio
1368///               async_std
1369/// 
1370///         edit( 
1371///              def,
1372///              imp(..),
1373///              trt(..),
1374///             ) 
1375/// 
1376///         Mutex | RwLock *
1377///                
1378///         file = path/to/current/file.rs
1379///         
1380///         name = "" 
1381/// 
1382///         show
1383/// 
1384///         debut
1385/// 
1386///         actor(  
1387///                 first_name = "" 
1388/// 
1389///                 edit( 
1390///                     script(..)
1391///                     live(..)
1392///                     ) 
1393/// 
1394///                 include|exclude 
1395/// 
1396///                 show
1397/// 
1398///                 interact
1399///             )
1400/// 
1401/// )]
1402/// 
1403/// ~  -  override 
1404/// *  -  default 
1405/// ```
1406/// 
1407/// Options marked with `~` in the schema are inherited by default but can be overridden in the `actor` configuration.
1408/// 
1409/// The original `actor`'s  option `name` is different (`first_name` mandatory ) whereas `name` is 
1410/// optional part of `family`. The naming convention for an object named Actor is:
1411///     - for family  `Actor + Family` ( if not `name` specified )
1412///     - for actors `FirstName + Actor + Live|Script`
1413/// 
1414/// Consider the following example of a `family` macro:
1415/// ```text
1416/// #[interthread::family(
1417///     name = "MyActor",
1418///     Mutex, 
1419///     edit(file),
1420///     lib, 
1421///     channel,
1422///     debut,
1423/// 
1424///     actor(first_name = "User", include(foo)),  
1425///     actor(first_name = "Admin", include(foo, bar)),
1426/// )]
1427/// 
1428/// ```
1429/// will generate types named:
1430/// 
1431/// ```rust no_run
1432/// 
1433/// struct MyActorFamily {
1434///     pub user: UserMyActorLive,
1435///     pub admin: AdminMyActorLive,
1436/// }
1437/// // the script parts
1438/// UserMyActorScript 
1439/// AdminMyActorScript
1440/// 
1441/// ```
1442/// Behind the scenes, individual Actor Models are created for each member of the `family`,
1443/// sharing the same `Actor` object which is wrapped in either an `Arc<Mutex<Actor>>` 
1444/// or an `Arc<RwLock<Actor>>`, depending on the specified lock type.
1445/// 
1446/// Within the `Script::direct` method, immediately after the `Script` variant match, 
1447/// the `Actor` object is locked, and the corresponding method is invoked.
1448/// 
1449/// For developers seeking full control over the locking mechanism, the `family` 
1450/// macro provides a convention for defining static methods with a specific receiver. 
1451/// 
1452/// If a static method in the `Actor` implementation body uses a receiver 
1453/// named `actor` and its type matches the shared model type (`Arc<Mutex<Actor>>` or `Arc<RwLock<Actor>>`), 
1454/// the macro interprets this as a custom model method rather than a standard static method.
1455/// 
1456/// For example, consider the following method inside an Actor implementation:
1457/// ```rust no_run
1458/// impl Actor {
1459///     pub fn method(actor: &Arc<RwLock<Self>>, s: Type) -> Type {
1460///         let actor = actor.read().unwrap();
1461///         // Perform operations using the actor
1462///     }
1463/// }
1464/// ```
1465/// When processed by the macro, this method will be interpreted in `ActorLive` instance as:
1466/// 
1467/// ```rust no_run
1468/// impl ActorLive {
1469///     pub fn method(&self, s: Type) -> Type {
1470///         ...
1471///     }
1472/// }
1473/// ```
1474/// and processed correspondingly in `ActorScript`.
1475/// 
1476/// ### Supported Runtimes
1477/// The macro supports the following runtimes, each using its respective `Mutex` implementation:
1478/// 
1479/// 
1480/// |   Runtime  |    Mutex   |  RwLock |  
1481/// |:------------------------:|:----------:|:----------:|
1482/// | `std` (standard library) | `std::sync::Mutex`|`std::sync::RwLock` | 
1483/// | `tokio` | `tokio::sync::Mutex`|`tokio::sync::RwLock` | 
1484/// | `async-std` | `async_std::sync::Mutex`|`async_std::sync::RwLock` | 
1485/// 
1486/// The `smol` runtime does not support the `family` macro.
1487
1488
1489#[proc_macro_error::proc_macro_error]
1490#[proc_macro_attribute]
1491pub fn family( attr: proc_macro::TokenStream, item: proc_macro::TokenStream ) -> proc_macro::TokenStream {
1492    
1493    let item_impl = syn::parse_macro_input!(item as syn::ItemImpl);
1494
1495    let nested  = syn::parse_macro_input!(attr with syn::punctuated::Punctuated::<syn::Meta,syn::Token![,]>::parse_terminated); 
1496    let mut aaa = model::attribute::ActorAttributeArguments::from(nested, crate::model::Mac::Family);
1497    aaa.cross_check();
1498
1499    check::channels_import( &aaa.lib );
1500
1501    let edit_attr = aaa.edit.attr.clone();
1502    let mut model_sdpl = crate::model::generate_model( aaa, &item_impl);
1503    let (code,edit_sdpl) = model_sdpl.get_code_edit();
1504
1505    if let Some( edit_attr ) = edit_attr {
1506
1507        parse::edit_write( &edit_attr, &item_impl, edit_sdpl);
1508    }
1509
1510    quote::quote!{
1511        #item_impl
1512        #code
1513    }.into()
1514
1515}
1516
1517
1518
1519
1520
1521
1522
1523
1524