1#![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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
233pub enum TransferError
234{
235 AlreadyTransfered,
237
238 AlreadyReturned,
241
242 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#[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#[repr(align(4))]
294#[derive(Debug, Clone, PartialEq, Eq)]
295struct OwnershipFlags
296{
297 owned: bool,
299
300 poisoned: bool,
302
303 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 #[inline]
399 fn is_owned(&self) -> bool
400 {
401 return self.owned;
402 }
403
404 #[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 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 fn clear_poison(&mut self)
455 {
456 self.poisoned = false;
457 }
458
459 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 #[derive(Debug)]
474 pub struct OwnerInner<ITEM: Send + fmt::Debug>
475 {
476 flags: AtomicU32,
478
479 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 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 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 #[derive(Debug)]
711 pub struct OwnerInner<ITEM: Send + fmt::Debug>
712 {
713 flags: Mutex<OwnershipFlags>,
715
716 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 pub(crate)
767 fn return_ownership(&self, poison_guard: &TransferPanicGuard) -> bool
768 {
769 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#[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 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 unsafe { ptr::drop_in_place(self.owner_inner.as_ptr()) };
941
942 return;
943 }
944 }
945}
946
947#[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 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 #[inline]
992 fn inner(&self) -> &OwnerInner<ITEM>
993 {
994 return unsafe { self.0.as_ref() };
995 }
996
997 #[inline]
999 fn inner_mut(&mut self) -> &mut OwnerInner<ITEM>
1000 {
1001 return unsafe { self.0.as_mut() };
1002 }
1003
1004 #[inline]
1007 pub
1008 fn is_owned(&self) -> bool
1009 {
1010 return self.inner().is_owned();
1011 }
1012
1013 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 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 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 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 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 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(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 se.send(owner.transfer_ownership().unwrap()).unwrap();
1235
1236 let _ = thread_hndl.join();
1237
1238 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 owner.clear_poisoned(|v| {}).unwrap();
1252
1253 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 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(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 se.send(owner.transfer_ownership().unwrap()).unwrap();
1464
1465 let _ = thread_hndl.join();
1466
1467 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 owner.clear_poisoned(|itme| {}).unwrap();
1481
1482 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