temporary_owner_rs/
lib.rs

1/*-
2 * temporary-owner-rs - A crate which provides a temporary exclusive ownership 
3 * over the data which can be Send to other thread.
4 * 
5 * Copyright (C) 2025 Aleksandr Morozov
6 * 
7 * The scram-rs crate can be redistributed and/or modified
8 * under the terms of either of the following licenses:
9 *
10 *   1. the Mozilla Public License Version 2.0 (the “MPL”) OR
11 *                     
12 *   2. EUROPEAN UNION PUBLIC LICENCE v. 1.2 EUPL © the European Union 2007, 2016
13 */
14
15//! # This is an experimental crate!
16//! 
17//! <img src="https://cdn.4neko.org/ow_temp_transf_500.webp" width="280"/> <img src="https://cdn.4neko.org/source_avail.webp" width="280"/> <img src="https://cdn.4neko.org/mpl_or_eupl_500.webp" width="280"/>
18//! 
19//! A crate which provides a temporary transfer of the ownership over the 
20//! data structure to any other instance i.e thread. This is a sort of
21//! an exclusive access to the inner instance without the shared access.
22//! 
23//! There is no proofs yet that there is no single event which may 
24//! cause a race condition. The CPU must support `atomic` operation reordering
25//! otherwise it will not work.
26//! 
27//! Supports ![no_std] if feature `std` is not enabled.
28//! 
29//! ```text
30//!                      ┌───────────────────┐                                         
31//!                      │                   │                                         
32//!                      │     ItemOwner     │◄───────────────────────────────────────┐
33//!                      │                   │                                        │
34//!                      └────────┬──────────┘                                        │
35//!                               │                                                   │
36//!                               │                                                   │
37//!                               │                                                   │
38//!                               │                                                   │
39//!                     ┌─────────▼──────────────┐                                    │
40//!                     │                        │                                    │
41//!                     │  transfer_ownership()  │                                    │
42//!                     │                        │                                    │
43//!                     └────┬──┬──┬─────────────┘                                    │
44//!                          │  │  │                                                  │
45//!                          │  │  │  ───────────────────────────────────────         │
46//!                          │  │  │         EXCLUSIVE ACCESS                         │
47//! ┌──────────────────┐     │  │  │     ┌───────────────────────────┐                │
48//! │                  │     │  │  │     │         INSTANCE          │                │
49//! │                  ◄─────┘  │  └─────►                           │                │
50//! │  TransferError   │        │        │    ItemOwnershipTransfer  │                │
51//! ├──────────────────┘        │        └────────────┬──────────────┘                │
52//! │                           │                     │                               │
53//! ├── AlreadyTransfered       │                     │                               │
54//! │                           │          ┌──────────▼─────────────┐                 │
55//! │                           │          │     send_over_MPSC     │                 │
56//! ├── AlreadyReturned         │          └────────────────────────┘                 │
57//! │                           │                                                     │
58//! │                                                                                 │
59//! └── Poisoned                ───────    ────    ─────   ──────    ───    ───       │
60//!                                                                                   │
61//!                               ┌─────────────┐                                     │
62//!                               │  Thread N   │                                     │
63//!                               └─────────────┘─────────────────────┐               │
64//!                                       │       MPSC_RECV           │               │
65//!                                       │                           │               │
66//!                                       │   ItemOwnershipTransfer   │               │
67//!                                       └────────────┬──────────────┘               │
68//!                                                    │                              │
69//!                                                    │                              │
70//!                                            ┌───────▼──────────┐                   │
71//!                                            │   as_ref()       │                   │
72//!                                            │                  │                   │
73//!                                            │   as_mut()       │                   │
74//!                                            └───────┬──────────┘                   │
75//!                                                    │                              │
76//!                                                    │                              │
77//!                                            ┌───────▼──────────┐                   │
78//!                                            │   drop()         │                   │
79//!                                            │                  ┼───────────────────┘
80//!                                            └──────────────────┘                    
81//! ```
82//! 
83//! ## Examples
84//! 
85//! ```ignore
86//! use std::{fmt, sync::{atomic::{AtomicU32, Ordering}, mpsc}, time::Duration};
87//! 
88//! use crate::{ItemOwner, ItemOwnershipTransfer, OwnershipFlags, TransferError};
89//! 
90//! // used for example only
91//! pub trait PeriodicTask: Send + fmt::Debug
92//! {
93//!     fn exec(&mut self) -> Result<(), String>;
94//!     fn get_val(&self) -> u32;
95//! }
96//! 
97//! pub type PeriodicTaskHndl = Box<dyn PeriodicTask>;
98//! 
99//! 
100//! #[derive(Debug)]
101//! pub struct Task1
102//! {
103//!     val: u32
104//! }
105//! 
106//! impl Drop for Task1
107//! {
108//!     fn drop(&mut self) 
109//!     {
110//!         println!("dropped!");
111//!     }
112//! }
113//! 
114//! impl PeriodicTask for Task1
115//! {
116//!     fn get_val(&self) -> u32
117//!     {
118//!         return self.val;
119//!     }
120//! 
121//!     fn exec(&mut self) -> Result<(), String> 
122//!     {
123//!         println!("task {} called", self.val);
124//! 
125//!         return Ok(());
126//!     }
127//! }
128//! 
129//! fn main()
130//! {
131//!     let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
132//! 
133//!     // creating new instance
134//!     let owner = ItemOwner::new(task1);
135//! 
136//!     // creating channel to send the shared item
137//!     let (se, rc) = 
138//!         mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
139//! 
140//!     let thread_hndl = 
141//!         std::thread::spawn(move || 
142//!             {
143//!                 // receive the transfered ownership
144//!                 let mut task = rc.recv().unwrap();
145//! 
146//!                 std::thread::sleep(Duration::from_secs(2));
147//! 
148//!                 // call task
149//!                 task.as_mut().exec().unwrap();
150//! 
151//!                 return;
152//!             }
153//!         );
154//! 
155//! 
156//!     se.send(owner.transfer_ownership().unwrap()).unwrap();
157//! 
158//!     // wait when the ownership will be returned
159//!     while owner.is_owned() == false
160//!     {
161//!         std::thread::sleep(Duration::from_secs(1));
162//!     }
163//! 
164//!     println!("completed round 1");
165//! 
166//!     thread_hndl.join().unwrap();
167//! 
168//!     let (se, rc) = 
169//!         mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
170//! 
171//!     let thread_hndl = 
172//!         std::thread::spawn(move || 
173//!             {
174//!                 let mut task = rc.recv().unwrap();
175//! 
176//!                 std::thread::sleep(Duration::from_secs(2));
177//!                 task.as_mut().exec().unwrap();
178//! 
179//!                 return;
180//!             }
181//!         );
182//! 
183//!     se.send(owner.transfer_ownership().unwrap()).unwrap();
184//! 
185//!     while owner.is_owned() == false
186//!     {
187//!         std::thread::sleep(Duration::from_secs(1));
188//!     }
189//! 
190//!     println!("completed round 2");
191//! 
192//!     thread_hndl.join().unwrap();
193//! 
194//! 
195//!     return;
196//! }
197//! ```
198
199#![cfg_attr(not(feature = "std"), no_std)]
200
201#[cfg(not(feature = "std"))]
202extern crate alloc;
203
204#[cfg(not(feature = "std"))]
205use alloc::boxed::Box;
206
207#[cfg(not(feature = "std"))]
208use core::
209{
210    fmt, 
211    mem, 
212    ops::{Deref, DerefMut}, 
213    ptr::{self, NonNull}, 
214    sync::atomic::{AtomicU32, Ordering}
215};
216
217#[cfg(not(feature = "std"))]
218use alloc::string::ToString;
219
220#[cfg(feature = "std")]
221use std::
222{
223    fmt, 
224    mem, 
225    ops::{Deref, DerefMut}, 
226    ptr::{self, NonNull}, 
227    sync::atomic::{AtomicU32, Ordering}
228};
229
230
231/// Error code which describes what happened.
232#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum TransferError
234{
235    /// A ownership has been already transferred and have not yet been released i.e WouldBlock.
236    AlreadyTransfered,
237
238    /// A ownership have been already returned. This is normally used for the assertions trap and
239    /// never returned to the user.
240    AlreadyReturned,
241
242    /// A transfer is not possible because the instance is poisoned due to the thread which owns a
243    /// transfer has paniced.
244    Poisoned,
245}
246
247impl fmt::Display for TransferError
248{
249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
250    {
251        match self
252        {
253            Self::AlreadyTransfered => 
254                write!(f, "instance have been already transferred!"),
255            Self::AlreadyReturned => 
256                write!(f, "instance have been already returned!"),
257            Self::Poisoned => 
258                write!(f, "transfer was not returned due to the thread panic"),
259        }
260    }
261}
262
263/// A guard which is assigned to the [ItemOwnershipTransfer] for the execution flow
264/// control. 
265#[derive(Clone, Debug)]
266struct TransferPanicGuard
267{
268    #[cfg(all(panic = "unwind", feature = "std"))]
269    panicking: bool,
270}
271
272#[cfg(all(panic = "unwind", feature = "std"))]
273impl Default for TransferPanicGuard
274{
275    fn default() -> Self 
276    {
277        use std::thread;
278
279        Self { panicking: thread::panicking() }
280    }
281}
282
283#[cfg(any(not(panic = "unwind"), not(feature = "std")))]
284impl Default for TransferPanicGuard
285{
286    fn default() -> Self 
287    {
288        Self { }
289    }
290}
291
292/// A flags which defines the current state of the instance.
293#[repr(align(4))]
294#[derive(Debug, Clone, PartialEq, Eq)]
295struct OwnershipFlags
296{
297    /// Tells if instance is owned (true) or transferred.
298    owned: bool, 
299
300    /// The last transfer was not completed i.e thread paniced.
301    poisoned: bool,
302
303    /// If set to true, the transfer should deallocate the inner type in drop
304    drop_in_place: bool,
305}
306
307impl fmt::Display for OwnershipFlags
308{
309    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
310    {
311        let o = 
312            if self.owned == true
313            {
314                "Owned"
315            }
316            else
317            {
318                "~Owned"
319            };
320
321        let p = 
322            if self.poisoned == true
323            {
324                "Poisoned"
325            }
326            else
327            {
328                "~Poisoned"
329            };
330
331        let d = 
332            if self.drop_in_place == true
333            {
334                "Drop"
335            }
336            else
337            {
338                "~Drop"
339            };
340
341        write!(f, "{},{},{}", o, p ,d)
342    }
343}
344
345impl From<u32> for OwnershipFlags
346{
347    fn from(value: u32) -> Self
348    {
349        return unsafe { mem::transmute(value) };
350    }
351}
352
353impl From<OwnershipFlags> for u32
354{
355    fn from(value: OwnershipFlags) -> Self
356    {
357        return unsafe { mem::transmute(value) };
358    }
359}
360
361impl Default for OwnershipFlags
362{
363    fn default() -> Self
364    {
365        return
366            Self
367            {
368                owned: true,
369                poisoned: false,
370                drop_in_place: false,
371            };
372    }
373}
374
375
376
377impl OwnershipFlags
378{
379    #[inline]
380    const 
381    fn make_transfer() -> OwnershipFlags
382    {
383        return OwnershipFlags { owned: false, poisoned: false, drop_in_place: false };
384    }
385
386    #[inline] 
387    fn make_return(poison_guarg: &TransferPanicGuard) -> OwnershipFlags
388    {
389        let mut val = OwnershipFlags { owned: true, poisoned: false, drop_in_place: false };
390
391        val.return_transfer(poison_guarg);
392
393        return val;
394    }
395
396    /// Returns `true` if instance is owned by the [ItemOwner]. 
397    /// Should not be called from the [ItemOwnershipTransfer].
398    #[inline]
399    fn is_owned(&self) -> bool
400    {
401        return self.owned;
402    }
403
404    /// Transfers the `ownership` temporary if it was not previously:
405    /// 
406    /// * already presented to other [ItemOwnershipTransfer] instance.
407    /// 
408    /// * the instance is not poisoned.
409    #[inline]
410    fn transfer(&mut self) -> Result<TransferPanicGuard, TransferError>
411    {
412        let guard = TransferPanicGuard::default();
413
414        if self.owned == true && self.poisoned == false
415        {
416            self.owned = false;
417
418            return Ok(guard);
419        }
420        else if self.poisoned == true
421        {
422            return Err(TransferError::Poisoned);
423        }
424
425        return Err(TransferError::AlreadyTransfered);
426    }
427
428    /// A [ItemOwnershipTransfer] returns the thransferred exclusive right.
429    /// 
430    /// Panics if race condition or misuse happens (when returned multiple times)
431    fn return_transfer(&mut self, poison_guarg: &TransferPanicGuard)
432    {
433        #[cfg(all(panic = "unwind", feature = "std"))]
434        if poison_guarg.panicking == false && std::thread::panicking() == true
435        {
436            self.poisoned = true;
437            self.owned = true;
438
439            return;
440        }
441
442        #[cfg(not(all(panic = "unwind", feature = "std")))]
443        let _ = poison_guarg;
444
445        if self.owned == false
446        {
447            self.owned = true;
448        }
449
450        return;
451    }
452
453    /// Clears the poisoned status.
454    fn clear_poison(&mut self)
455    {
456        self.poisoned = false;
457    }
458
459    /// Sets the `drop-in-place` status.
460    fn drop_in_place(&mut self)
461    {
462        self.drop_in_place = true;
463    }
464}
465
466
467#[cfg(target_has_atomic = "64")]
468mod has_atomics
469{
470    use super::*;
471
472    /// Inner type which is not exposed.
473    #[derive(Debug)]
474    pub struct OwnerInner<ITEM: Send + fmt::Debug>
475    {
476        /// A [OwnershipFlags] represented as atomic u32.
477        flags: AtomicU32,
478
479        /// An item to share.
480        item: Option<ITEM>,
481    }
482
483    unsafe impl<ITEM: Send  + fmt::Debug> Sync for OwnerInner<ITEM> {}
484
485    impl<ITEM: Send + fmt::Debug> Deref for OwnerInner<ITEM>
486    {
487        type Target = ITEM;
488
489        #[inline]
490        fn deref(&self) -> &Self::Target
491        {
492            return self.item.as_ref().unwrap();
493        }
494    }
495
496    impl<ITEM: Send + fmt::Debug> DerefMut for OwnerInner<ITEM>
497    {
498        #[inline]
499        fn deref_mut(&mut self) -> &mut Self::Target
500        {
501            return self.item.as_mut().unwrap();
502        }
503    }
504
505    impl<ITEM: Send  + fmt::Debug> OwnerInner<ITEM>
506    {
507        pub(crate) 
508        fn new(item: ITEM) -> Self
509        {
510            return
511                Self
512                {
513                    flags: 
514                        AtomicU32::new(OwnershipFlags::default().into()),
515                    item: 
516                        Some(item)
517                };
518        }
519
520        pub(crate) 
521        fn transfer_ownership(&self) -> Result<TransferPanicGuard, TransferError>
522        {
523           // let inner = self.inner();
524
525            let cur: OwnershipFlags = self.flags.load(Ordering::Relaxed).into();
526            let mut new = cur.clone();
527            let transfer = new.transfer()?;
528            
529            let res = 
530                self
531                    .flags
532                    .compare_exchange_weak(cur.into(), new.into(), Ordering::SeqCst, Ordering::Acquire);
533
534            match res 
535            {
536                Ok(_) =>
537                    return Ok( transfer ),
538                Err(e) =>
539                {
540                    let mut cur: OwnershipFlags = self.flags.load(Ordering::Relaxed).into();
541
542                    let _ = cur.transfer()?;
543
544                    return Err(TransferError::AlreadyReturned);
545                }
546            }
547        }
548
549        /// Returns `true` if drop-in-place is required.
550        pub(crate) 
551        fn return_ownership(&self, poison_guard: &TransferPanicGuard) -> bool
552        {
553            let new_flags = OwnershipFlags::make_return(poison_guard);
554
555            let res = 
556                self
557                    .flags
558                    .compare_exchange_weak(
559                        new_flags.clone().into(), 
560                        new_flags.clone().into(), 
561                        Ordering::SeqCst, 
562                        Ordering::Acquire
563                    );
564
565            if let Ok(val) = res
566            {
567                panic!("assertion trap: already returned val: {}, valflags: {}", val, OwnershipFlags::from(val));
568            }
569
570            let cur_flags: OwnershipFlags = res.err().unwrap().into();
571
572            if cur_flags.drop_in_place == true
573            {
574                return true;
575            }
576            
577            let res = 
578                self
579                    .flags
580                    .compare_exchange_weak(
581                        cur_flags.clone().into(), 
582                        new_flags.clone().into(), 
583                        Ordering::SeqCst, 
584                        Ordering::Acquire
585                    );
586
587            if let Err(e) = res
588            {
589                panic!("assertion trap: can not return ownership, expected: '{}', got: '{}", cur_flags, new_flags);
590            }
591
592            return false;
593        }
594
595        pub(crate) 
596        fn get_owner_flags(&self) -> Option<OwnershipFlags>
597        {
598            return Some(
599                self
600                    .flags
601                    .load(Ordering::Relaxed)
602                    .into()
603            );
604        }
605
606        pub(crate) 
607        fn get_item(&self) -> Option<&ITEM>
608        {
609            return self.item.as_ref();
610        }
611
612        pub(crate) 
613        fn is_owned(&self) -> bool
614        {
615            let flags: OwnershipFlags = self.flags.load(Ordering::SeqCst).into();
616
617            return flags.is_owned();
618        }
619
620        pub(crate) 
621        fn clear_poisoned_mut<F>(&mut self, check_f: F) -> Result<(), TransferError>
622        where F: FnOnce(&mut ITEM)
623        {
624            let mut flags: OwnershipFlags = self.flags.load(Ordering::Relaxed).into();
625
626            if flags.is_owned() == false
627            {
628                return Err(TransferError::AlreadyTransfered);
629            }
630
631            (check_f)(self.item.as_mut().unwrap());
632
633            flags.clear_poison();
634
635            self.flags.store(flags.into(), Ordering::Relaxed);
636
637            return Ok(());
638        }
639
640        pub(crate) 
641        fn clear_poisoned<F>(&self, check_f: F) -> Result<(), TransferError>
642        where F: FnOnce(&ITEM)
643        {
644            let mut flags: OwnershipFlags = self.flags.load(Ordering::Relaxed).into();
645
646            if flags.is_owned() == false
647            {
648                return Err(TransferError::AlreadyTransfered);
649            }
650
651            (check_f)(self.item.as_ref().unwrap());
652
653            flags.clear_poison();
654
655            self.flags.store(flags.into(), Ordering::Relaxed);
656
657            return Ok(());
658        }
659
660
661        pub(crate)  
662        fn try_into_inner(&mut self, is_drop: bool) -> Result<ITEM, TransferError>
663        {
664            let mut flags: OwnershipFlags = self.flags.load(Ordering::Relaxed).into();
665
666            if flags.owned == true 
667            {
668                let buf = self.item.take().unwrap();
669
670                return Ok(buf);
671            }
672            else 
673            {
674                if is_drop == true
675                {
676                    let cur_flags = flags.clone();
677                    flags.drop_in_place();
678
679                    let res = 
680                        self
681                            .flags
682                            .compare_exchange_weak(cur_flags.clone().into(), flags.clone().into(), Ordering::SeqCst, Ordering::Acquire);
683                    
684                    if let Ok(_) = res
685                    {
686                        return Err(TransferError::AlreadyTransfered);
687                    }
688
689                    return self.try_into_inner(is_drop);
690                }
691
692                return Err(TransferError::AlreadyTransfered);
693            }
694        }
695    }
696}
697
698#[cfg(target_has_atomic = "64")]
699use self::has_atomics::*;
700
701
702#[cfg(not(target_has_atomic = "64"))]
703mod not_atomics
704{
705    use std::sync::Mutex;
706
707    use super::*;
708    
709    /// Inner type which is not exposed.
710    #[derive(Debug)]
711    pub struct OwnerInner<ITEM: Send + fmt::Debug>
712    {
713        /// A [OwnershipFlags] represented as atomic u32.
714        flags: Mutex<OwnershipFlags>,
715
716        /// An item to share.
717        item: Option<ITEM>,
718    }
719
720    unsafe impl<ITEM: Send  + fmt::Debug> Sync for OwnerInner<ITEM> {}
721
722    impl<ITEM: Send + fmt::Debug> Deref for OwnerInner<ITEM>
723    {
724        type Target = ITEM;
725
726        #[inline]
727        fn deref(&self) -> &Self::Target
728        {
729            return self.item.as_ref().unwrap();
730        }
731    }
732
733    impl<ITEM: Send + fmt::Debug> DerefMut for OwnerInner<ITEM>
734    {
735        #[inline]
736        fn deref_mut(&mut self) -> &mut Self::Target
737        {
738            return self.item.as_mut().unwrap();
739        }
740    }
741
742    impl<ITEM: Send  + fmt::Debug> OwnerInner<ITEM>
743    {
744        pub(crate) 
745        fn new(item: ITEM) -> Self
746        {
747            return
748                Self
749                {
750                    flags: 
751                        Mutex::new(OwnershipFlags::default()),
752                    item: 
753                        Some(item)
754                };
755        }
756
757        pub(crate) 
758        fn transfer_ownership(&self) -> Result<TransferPanicGuard, TransferError>
759        {
760            let mut lock = self.flags.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
761
762           return lock.transfer();
763        }
764
765        /// Returns `true` if drop-in-place is required.
766        pub(crate) 
767        fn return_ownership(&self, poison_guard: &TransferPanicGuard) -> bool
768        {
769            // it is safe because the ItemOwnershipTransfer presents as signle instance
770            let mut lock = self.flags.lock().unwrap_or_else(std::sync::PoisonError::into_inner);
771
772            lock.return_transfer(poison_guard);
773
774            if lock.drop_in_place == true
775            {
776                return true;
777            }
778            
779            return false;
780        }
781
782        pub(crate) 
783        fn get_owner_flags(&self) -> Option<OwnershipFlags>
784        {
785            return 
786                self
787                    .flags
788                    .try_lock()
789                    .map_or(None, |f| Some(f.clone()));
790        }
791
792        pub(crate) 
793        fn get_item(&self) -> Option<&ITEM>
794        {
795            return self.item.as_ref();
796        }
797
798        #[inline]
799        pub(crate) 
800        fn is_owned(&self) -> bool
801        {
802            return self.flags.lock().unwrap_or_else(std::sync::PoisonError::into_inner).owned;
803        }
804
805        pub(crate) 
806        fn clear_poisoned_mut<F>(&mut self, check_f: F) -> Result<(), TransferError>
807        where F: FnOnce(&mut ITEM)
808        {
809            let mut lock = 
810                self
811                    .flags
812                    .lock()
813                    .unwrap_or_else(std::sync::PoisonError::into_inner);
814
815            (check_f)(self.item.as_mut().unwrap());
816
817            lock.clear_poison();
818
819            return Ok(());
820        }
821
822        pub(crate) 
823        fn clear_poisoned<F>(&self, check_f: F) -> Result<(), TransferError>
824        where F: FnOnce(&ITEM)
825        {
826            let mut lock = 
827                self
828                    .flags
829                    .lock()
830                    .unwrap_or_else(std::sync::PoisonError::into_inner);
831
832            (check_f)(self.item.as_ref().unwrap());
833
834            lock.clear_poison();
835
836            return Ok(());
837        }
838
839        pub(crate) 
840        fn try_into_inner(&mut self, is_drop: bool) -> Result<ITEM, TransferError>
841        {
842            let mut lock = 
843                self
844                    .flags
845                    .lock()
846                    .unwrap_or_else(std::sync::PoisonError::into_inner);
847
848            if lock.owned == true 
849            {
850                let buf = self.item.take().unwrap();
851
852                return Ok(buf);
853            }
854            else 
855            {
856                if is_drop == true
857                {
858                    lock.drop_in_place = true;
859                }
860
861                return Err(TransferError::AlreadyTransfered);
862            }
863        }
864    }
865}
866
867#[cfg(not(target_has_atomic = "64"))]
868use self::not_atomics::*;
869    
870
871
872/// An instance which holds the exclusive lock and provides `ref` and `mut`
873/// dereferencing. This instance can be [Send] over to other threads which 
874/// would like to gain a temporary access.
875/// 
876/// If thread panics, the owner of the `ITEM` will be `poisoned` and should be
877/// restored manually.
878#[derive(Debug)]
879pub struct ItemOwnershipTransfer<ITEM: Send + fmt::Debug>
880{
881    poison_guard: TransferPanicGuard,
882    owner_inner: NonNull<OwnerInner<ITEM>>,
883}
884
885
886impl<ITEM: Send + fmt::Debug> ItemOwnershipTransfer<ITEM>
887{
888    #[inline]
889    fn new(inner: NonNull<OwnerInner<ITEM>>, poison_guard: TransferPanicGuard,) -> Self
890    {
891        return 
892            Self
893            {   poison_guard: poison_guard,
894                owner_inner: inner
895            };
896    }
897
898    #[cfg(test)]
899    #[inline]
900    fn inner(&self) -> &OwnerInner<ITEM>
901    {
902        return unsafe { self.owner_inner.as_ref() };
903    }
904}
905
906unsafe impl<ITEM: Send + fmt::Debug> Send for ItemOwnershipTransfer<ITEM> {}
907
908impl<ITEM: Send + fmt::Debug> Deref for ItemOwnershipTransfer<ITEM>
909{
910    type Target = ITEM;
911
912    fn deref(&self) -> &Self::Target
913    {
914        let inner = unsafe { self.owner_inner.as_ref() };
915
916        return inner;
917    }
918}
919
920impl<ITEM: Send + fmt::Debug> DerefMut for ItemOwnershipTransfer<ITEM>
921{
922    fn deref_mut(&mut self) -> &mut Self::Target
923    {
924        let inner = unsafe { self.owner_inner.as_mut() };
925
926        return inner;
927    }
928}
929
930impl<ITEM: Send + fmt::Debug> Drop for ItemOwnershipTransfer<ITEM>
931{
932    /// The instance may perform `drop_in_place` if there is no `base` references.
933    fn drop(&mut self)
934    {
935        let inner = unsafe { self.owner_inner.as_ref() };
936
937        if inner.return_ownership(&self.poison_guard) == true
938        {
939            // call descrutor
940            unsafe { ptr::drop_in_place(self.owner_inner.as_ptr()) };
941
942            return;
943        }
944    }
945}
946
947/// An owner of the intance `ITEM` which holds the exclusive rights.
948/// It may temporary transfer the ownership over `ITEM` and `Send` it
949/// to other thread. The transfered ownership is defined by [ItemOwnershipTransfer]
950/// which is a temporary container.
951/// 
952/// The ownership cannot be transferred simultaniously twice, so the exclusive 
953/// R/W access is guaranteed.
954/// 
955/// In case of the [ItemOwner] dropeed before the [ItemOwnershipTransfer] releases 
956/// the transfer, the [ItemOwnershipTransfer] would drop the data in place.
957/// 
958/// The `ITEM` can be returned from the instance only if no-exclusive transfer is
959/// pending.
960/// 
961/// The `ITEM` must be [Send] and implement [fmt::Debug].
962#[derive(Debug, PartialEq, Eq)]
963pub struct ItemOwner<ITEM: Send + fmt::Debug>( NonNull<OwnerInner<ITEM>> );
964
965impl<ITEM: Send + fmt::Debug> fmt::Display for  ItemOwner<ITEM>
966{
967    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result 
968    {
969        let flags = 
970            self
971                .inner()
972                .get_owner_flags()
973                .map_or("locked".into(), |f| f.to_string());
974
975        write!(f, "flags: {}, item: {:?}", flags, self.inner().get_item())
976    }
977}
978
979impl<ITEM: Send + fmt::Debug>  ItemOwner<ITEM>
980{
981    /// Creates new instance.
982    pub 
983    fn new(item: ITEM) -> Self
984    {
985        let status = Box::new(OwnerInner::new(item));
986
987        return Self(Box::leak(status).into());
988    }
989
990    /// Returns the reference to the`inner` [OwnerInner] type. Must never be exposed outside.
991    #[inline]
992    fn inner(&self) -> &OwnerInner<ITEM>
993    {
994        return unsafe { self.0.as_ref() };
995    }
996
997    /// Returns the reference to the`inner` [OwnerInner] type. Must never be exposed outside.
998    #[inline]
999    fn inner_mut(&mut self) -> &mut OwnerInner<ITEM>
1000    {
1001        return unsafe { self.0.as_mut() };
1002    }
1003
1004    /// Checks if the instance owns the `ITEM`. If transfer is still pending `false` will be 
1005    /// retruned and no `transfer_ownership` is possible.
1006    #[inline]
1007    pub 
1008    fn is_owned(&self) -> bool
1009    {
1010        return self.inner().is_owned();
1011    }
1012
1013    /// Initiates the tmporary transfer of the ownership. If the exclusive lock is available
1014    /// i.e no transfer is penfing an [ItemOwnershipTransfer] will be returned which can be
1015    /// [Send] i.e over channel. 
1016    /// 
1017    /// Returns [Result::Err] 
1018    /// 
1019    /// * with [TransferError::AlreadyTransfered] only if transfer is still pending.
1020    /// 
1021    /// * with [TransferError::Poisoned] only if thread which used the trnasfer paniced.
1022    /// 
1023    /// * with [TransferError::AlreadyReturned] only if attempt faild and should be repeated.
1024    pub 
1025    fn transfer_ownership(&self) -> Result<ItemOwnershipTransfer<ITEM>, TransferError>
1026    {
1027        let inner = self.inner();
1028
1029        let transfer = inner.transfer_ownership()?;
1030
1031        return Ok( ItemOwnershipTransfer::new(self.0.clone(), transfer) );
1032    }
1033
1034    /// Attempts to clear the poisoned status. If instance is `poisoned` i.e thread to which
1035    /// the ownership was temporary transferred paniced, it should be cleaned manyally otherwise
1036    /// the `transfer_ownership` would return [TransferError::Poisoned].
1037    pub 
1038    fn clear_poisoned_mut<F>(&mut self, check_f: F) -> Result<(), TransferError>
1039    where F: FnOnce(&mut ITEM)
1040    {
1041        let inner = self.inner_mut();
1042
1043        return inner.clear_poisoned_mut(check_f);
1044    }
1045
1046    /// Attempts to clear the poisoned status. If instance is `poisoned` i.e thread to which
1047    /// the ownership was temporary transferred paniced, it should be cleaned manyally otherwise
1048    /// the `transfer_ownership` would return [TransferError::Poisoned].
1049    pub 
1050    fn clear_poisoned<F>(&self, check_f: F) -> Result<(), TransferError>
1051    where F: FnOnce(&ITEM)
1052    {
1053        let inner = self.inner();
1054
1055        return inner.clear_poisoned(check_f);
1056    }
1057
1058    /// Attempts to consume `Self` to return the `ITEM` from the instance.
1059    /// 
1060    /// This is only possible if instance is not `poisoned` and `owned`.
1061    /// 
1062    /// In case of success, the `ITEM` will be returned, otherwise the 
1063    /// `Self` and [TransferError] will be returned.
1064    /// 
1065    /// * [TransferError::AlreadyTransfered] - if item is still stransferred.
1066    pub 
1067    fn try_into_inner(mut self) -> Result<ITEM, (Self, TransferError)>
1068    {
1069        let res =
1070            self
1071                .inner_mut()
1072                .try_into_inner(false);
1073
1074        if let Ok(r) = res
1075        {
1076            drop(self);
1077
1078            return Ok(r);
1079        }
1080
1081        return res.map_err(|e| (self, e));
1082    }
1083}
1084
1085impl<ITEM: Send + fmt::Debug> Drop for ItemOwner<ITEM>
1086{
1087    fn drop(&mut self) 
1088    {
1089        let res =
1090            self
1091                .inner_mut()
1092                .try_into_inner(true);
1093
1094        if let Ok(_) = res
1095        {
1096            // call descrutor
1097            unsafe { ptr::drop_in_place(self.0.as_ptr()) };
1098        }
1099        
1100        return;
1101    }
1102}
1103
1104
1105#[cfg(all(feature = "std", target_has_atomic = "64"))]
1106#[cfg(test)]
1107mod test 
1108{
1109    use std::{fmt, sync::{atomic::{AtomicU32, Ordering}, mpsc}, time::Duration};
1110
1111    use crate::{ItemOwner, ItemOwnershipTransfer, OwnershipFlags, TransferError};
1112
1113    pub trait PeriodicTask: Send + fmt::Debug
1114    {
1115        fn exec(&mut self) -> Result<(), String>;
1116        fn get_val(&self) -> u32;
1117    }
1118
1119    pub type PeriodicTaskHndl = Box<dyn PeriodicTask>;
1120
1121    static DROP_FLAG: AtomicU32 = AtomicU32::new(0);
1122
1123    #[derive(Debug)]
1124    pub struct Task1
1125    {
1126        val: u32
1127    }
1128
1129    impl Drop for Task1
1130    {
1131        fn drop(&mut self) 
1132        {
1133            DROP_FLAG.fetch_add(1, Ordering::AcqRel);
1134            println!("dropped!");
1135        }
1136    }
1137
1138    impl PeriodicTask for Task1
1139    {
1140        fn get_val(&self) -> u32
1141        {
1142            return self.val;
1143        }
1144
1145        fn exec(&mut self) -> Result<(), String> 
1146        {
1147            println!("task {} called", self.val);
1148
1149            return Ok(());
1150        }
1151    }
1152
1153    #[test]
1154    fn test_a1()
1155    {
1156        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1157        let owner = ItemOwner::new(task1);
1158
1159        let transf = owner.transfer_ownership().unwrap();
1160
1161        assert_eq!(owner.is_owned(), false);
1162        
1163        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1164        assert_eq!(flags.owned, false);
1165        assert_eq!(flags.poisoned, false);
1166        assert_eq!(flags.drop_in_place, false);
1167
1168        assert_eq!(transf.as_ref().get_val(), 2);
1169
1170        drop(transf);
1171        
1172        assert_eq!(owner.is_owned(), true);
1173
1174        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1175        assert_eq!(flags.owned, true);
1176        assert_eq!(flags.poisoned, false);
1177        assert_eq!(flags.drop_in_place, false);
1178
1179
1180        let mut transf = owner.transfer_ownership().unwrap();
1181        let transf_dup = owner.transfer_ownership();
1182        assert_eq!(transf_dup.is_err(), true);
1183        assert_eq!(transf_dup.err(), Some(TransferError::AlreadyTransfered));
1184
1185        // just call to avoid optimizing
1186        transf.as_mut().exec().unwrap();
1187
1188        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1189        assert_eq!(flags.owned, false);
1190        assert_eq!(flags.poisoned, false);
1191        assert_eq!(flags.drop_in_place, false);
1192
1193        println!("{}", owner);
1194
1195        // drop the owner to test the drop in place
1196        drop(owner);
1197
1198        let flags: OwnershipFlags = transf.inner().get_owner_flags().unwrap();
1199        assert_eq!(flags.owned, false);
1200        assert_eq!(flags.poisoned, false);
1201        assert_eq!(flags.drop_in_place, true);
1202
1203        drop(transf);
1204
1205        assert_eq!(DROP_FLAG.load(Ordering::Acquire), 1);
1206    }
1207    
1208    #[test]
1209    #[should_panic(expected = "should panic!")]
1210    fn test_a2()
1211    {
1212        DROP_FLAG.store(0, Ordering::SeqCst);
1213
1214        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1215        let owner = ItemOwner::new(task1);
1216
1217        let (se, rc) = 
1218            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1219
1220            
1221        let thread_hndl = 
1222            std::thread::spawn(move || 
1223                {
1224                    let _task = rc.recv().unwrap();
1225
1226                    panic!("should panic!");
1227
1228                }
1229            );
1230
1231        
1232
1233        // send ownership transfer over
1234        se.send(owner.transfer_ownership().unwrap()).unwrap();
1235
1236        let _ = thread_hndl.join();
1237
1238        // check if poisoned.
1239        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1240        assert_eq!(flags.owned, true);
1241        assert_eq!(owner.is_owned(), true);
1242        assert_eq!(flags.poisoned, true);
1243        assert_eq!(flags.drop_in_place, false);
1244
1245
1246        let transf = owner.transfer_ownership();
1247        assert_eq!(transf.is_err(), true);
1248        assert_eq!(transf.err(), Some(TransferError::Poisoned));
1249
1250        // clear poison
1251        owner.clear_poisoned(|v| {}).unwrap();
1252
1253        // reaquie transfer
1254        let transf = owner.transfer_ownership();
1255        assert_eq!(transf.is_ok(), true);
1256
1257        drop(transf);
1258        drop(owner);
1259
1260        assert_eq!(DROP_FLAG.load(Ordering::Acquire), 1);
1261
1262        panic!("should panic!");
1263    }
1264
1265    #[test]
1266    fn test_a3()
1267    {
1268        DROP_FLAG.store(0, Ordering::SeqCst);
1269        
1270        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1271        let owner = ItemOwner::new(task1);
1272
1273        let (se, rc) = 
1274            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1275
1276        let thread_hndl = 
1277            std::thread::spawn(move || 
1278                {
1279                    let mut task = rc.recv().unwrap();
1280
1281                    std::thread::sleep(Duration::from_secs(2));
1282                    task.as_mut().exec().unwrap();
1283
1284                    return;
1285                }
1286            );
1287
1288
1289        se.send(owner.transfer_ownership().unwrap()).unwrap();
1290
1291        while owner.is_owned() == false
1292        {
1293            std::thread::sleep(Duration::from_secs(1));
1294        }
1295
1296        println!("completed round 1");
1297
1298        thread_hndl.join().unwrap();
1299
1300        let (se, rc) = 
1301            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1302
1303        let thread_hndl = 
1304            std::thread::spawn(move || 
1305                {
1306                    let mut task = rc.recv().unwrap();
1307
1308                    std::thread::sleep(Duration::from_secs(2));
1309                    task.as_mut().exec().unwrap();
1310
1311                    return;
1312                }
1313            );
1314
1315        se.send(owner.transfer_ownership().unwrap()).unwrap();
1316
1317        while owner.is_owned() == false
1318        {
1319            std::thread::sleep(Duration::from_secs(1));
1320        }
1321
1322        println!("completed round 2");
1323
1324        thread_hndl.join().unwrap();
1325
1326
1327        return;
1328    }
1329
1330    
1331}
1332    
1333
1334#[cfg(all(feature = "std", not(target_has_atomic = "64")))]
1335#[cfg(test)]
1336mod test 
1337{
1338    use std::{fmt, sync::{atomic::{AtomicU32, Ordering}, mpsc}, time::Duration};
1339
1340    use crate::{ItemOwner, ItemOwnershipTransfer, OwnershipFlags, TransferError};
1341
1342    pub trait PeriodicTask: Send + fmt::Debug
1343    {
1344        fn exec(&mut self) -> Result<(), String>;
1345        fn get_val(&self) -> u32;
1346    }
1347
1348    pub type PeriodicTaskHndl = Box<dyn PeriodicTask>;
1349
1350    static DROP_FLAG: AtomicU32 = AtomicU32::new(0);
1351
1352    #[derive(Debug)]
1353    pub struct Task1
1354    {
1355        val: u32
1356    }
1357
1358    impl Drop for Task1
1359    {
1360        fn drop(&mut self) 
1361        {
1362            DROP_FLAG.fetch_add(1, Ordering::AcqRel);
1363            println!("dropped!");
1364        }
1365    }
1366
1367    impl PeriodicTask for Task1
1368    {
1369        fn get_val(&self) -> u32
1370        {
1371            return self.val;
1372        }
1373
1374        fn exec(&mut self) -> Result<(), String> 
1375        {
1376            println!("task {} called", self.val);
1377
1378            return Ok(());
1379        }
1380    }
1381
1382    #[test]
1383    fn test_a1()
1384    {
1385        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1386        let owner = ItemOwner::new(task1);
1387
1388        let transf = owner.transfer_ownership().unwrap();
1389
1390        assert_eq!(owner.is_owned(), false);
1391        
1392        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1393        assert_eq!(flags.owned, false);
1394        assert_eq!(flags.poisoned, false);
1395        assert_eq!(flags.drop_in_place, false);
1396
1397        assert_eq!(transf.as_ref().get_val(), 2);
1398
1399        drop(transf);
1400        
1401        assert_eq!(owner.is_owned(), true);
1402
1403        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1404        assert_eq!(flags.owned, true);
1405        assert_eq!(flags.poisoned, false);
1406        assert_eq!(flags.drop_in_place, false);
1407
1408
1409        let mut transf = owner.transfer_ownership().unwrap();
1410        let transf_dup = owner.transfer_ownership();
1411        assert_eq!(transf_dup.is_err(), true);
1412        assert_eq!(transf_dup.err(), Some(TransferError::AlreadyTransfered));
1413
1414        // just call to avoid optimizing
1415        transf.as_mut().exec().unwrap();
1416
1417        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1418        assert_eq!(flags.owned, false);
1419        assert_eq!(flags.poisoned, false);
1420        assert_eq!(flags.drop_in_place, false);
1421
1422        println!("{}", owner);
1423
1424        // drop the owner to test the drop in place
1425        drop(owner);
1426
1427        let flags: OwnershipFlags = transf.inner().get_owner_flags().unwrap();
1428        assert_eq!(flags.owned, false);
1429        assert_eq!(flags.poisoned, false);
1430        assert_eq!(flags.drop_in_place, true);
1431
1432        drop(transf);
1433
1434        assert_eq!(DROP_FLAG.load(Ordering::Acquire), 1);
1435    }
1436    
1437    #[test]
1438    #[should_panic(expected = "should panic!")]
1439    fn test_a2()
1440    {
1441        DROP_FLAG.store(0, Ordering::SeqCst);
1442
1443        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1444        let owner = ItemOwner::new(task1);
1445
1446        let (se, rc) = 
1447            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1448
1449            
1450        let thread_hndl = 
1451            std::thread::spawn(move || 
1452                {
1453                    let _task = rc.recv().unwrap();
1454
1455                    panic!("should panic!");
1456
1457                }
1458            );
1459
1460        
1461
1462        // send ownership transfer over
1463        se.send(owner.transfer_ownership().unwrap()).unwrap();
1464
1465        let _ = thread_hndl.join();
1466
1467        // check if poisoned.
1468        let flags: OwnershipFlags = owner.inner().get_owner_flags().unwrap();
1469        assert_eq!(flags.owned, true);
1470        assert_eq!(owner.is_owned(), true);
1471        assert_eq!(flags.poisoned, true);
1472        assert_eq!(flags.drop_in_place, false);
1473
1474
1475        let transf = owner.transfer_ownership();
1476        assert_eq!(transf.is_err(), true);
1477        assert_eq!(transf.err(), Some(TransferError::Poisoned));
1478
1479        // clear poison
1480        owner.clear_poisoned(|itme| {}).unwrap();
1481
1482        // reaquie transfer
1483        let transf = owner.transfer_ownership();
1484        assert_eq!(transf.is_ok(), true);
1485
1486        drop(transf);
1487        drop(owner);
1488
1489        assert_eq!(DROP_FLAG.load(Ordering::Acquire), 1);
1490
1491        panic!("should panic!");
1492    }
1493
1494    #[test]
1495    fn test_a3()
1496    {
1497        DROP_FLAG.store(0, Ordering::SeqCst);
1498        
1499        let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
1500        let owner = ItemOwner::new(task1);
1501
1502        let (se, rc) = 
1503            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1504
1505        let thread_hndl = 
1506            std::thread::spawn(move || 
1507                {
1508                    let mut task = rc.recv().unwrap();
1509
1510                    std::thread::sleep(Duration::from_secs(2));
1511                    task.as_mut().exec().unwrap();
1512
1513                    return;
1514                }
1515            );
1516
1517
1518        se.send(owner.transfer_ownership().unwrap()).unwrap();
1519
1520        while owner.is_owned() == false
1521        {
1522            std::thread::sleep(Duration::from_secs(1));
1523        }
1524
1525        println!("completed round 1");
1526
1527        thread_hndl.join().unwrap();
1528
1529        let (se, rc) = 
1530            mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();
1531
1532        let thread_hndl = 
1533            std::thread::spawn(move || 
1534                {
1535                    let mut task = rc.recv().unwrap();
1536
1537                    std::thread::sleep(Duration::from_secs(2));
1538                    task.as_mut().exec().unwrap();
1539
1540                    return;
1541                }
1542            );
1543
1544        se.send(owner.transfer_ownership().unwrap()).unwrap();
1545
1546        while owner.is_owned() == false
1547        {
1548            std::thread::sleep(Duration::from_secs(1));
1549        }
1550
1551        println!("completed round 2");
1552
1553        thread_hndl.join().unwrap();
1554
1555
1556        return;
1557    }
1558
1559    
1560}
1561