temporary-owner-rs

Crates.iotemporary-owner-rs
lib.rstemporary-owner-rs
version0.2.0
created_at2025-09-01 02:16:08.957137+00
updated_at2025-09-21 23:37:48.420714+00
descriptionA crate which provides a temporary exclusive ownership over the data which can be Send to other thread
homepage
repositoryhttps://codeberg.org/4NEKO/temporary-owner-rs
max_upload_size
id1819037
size93,214
Aleksandr Morozov (eesekaj)

documentation

README

temporary-owner-rs

A kind of a RefCell which temporary transfers the owner rights to other thread providing exclusive access to the provided data.

The purpose of this crate is to provide an access to the inner item via temporary transferring the owner rights providing the exclusive access. The inner item must be Sync and Send because the main purpose is to share the instance with other threads by sending it via channel.

The locking is provided by the atomics with the Accure-Release ordering.

This crate is not tested completly!

Supports ![no_std] if feature std is not enabled.

Dual licensed crate.

Policy
  • This crate i.e code is NOT an Open Source software. This is a FREE (gratis) software and follows the principle of Sources Available/Disclosed software which should be fairly used.
  • It is published under FSF/OSI approved licenses however author does not follow/share/respect OSI and FSF principles and phylosophy.
  • License is subject to be changed in further versions without warning.
  • If you are using code in non-free (in terms of gratis) software you MUST NEVER demand a development of any features which are missing and needed for your business if you are not sponsoring/contributing those changes.
  • Access to the code can be limited by author to specific entities due to the local laws (not my bad or fault)(despite what is said in the license).
AI policy
  • AI generated sloppy code is prohibited. AI generates slop "a priori" (anyway).
  • Licenses (thank you OSS sectarians ) do not anyhow limit AI training, but f^ck you all - ChatGPT, CockPilot, especially Claude and rest unidentified cr@p.
  • It is strongly discouraged from using the AI based tools to write or enhance the code. AI slope would 100% violate the license by introducing the 3rd party licensed code.
Pull requests

The pull requests are now supported because the repository was moved to Codeberg. The alternative way is to send patches over the email to patch[at]4neko.org.

In case if you would like to contribute the code, please use pull request. Your pull request should include:

  • Description of changes and why it is needed.

  • Test the pull request.

    In case of you prefer email and patch files please consider the following:

  • For each feature or fix, please send patches separatly.

  • Please write what your patch is implementing or fixing.

  • I can read the code and I am able to understand it, so don't write a poem or essay in the description to the patches.

  • Please test your patch.

Questions about license MPL-2.0
  • Can I use the MPL-2.0 licensed code (crate) in larger project licensed with more permissive license like BSD or MIT.

I want to distribute (outside my organization) executable programs or libraries that I have compiled from someone else's unchanged MPL-licensed source code, either standalone or part of a larger work. What do I have to do?

You must inform the recipients where they can get the source for the MPLed code in the executable program or library you are distributing (i.e., you must comply with Section 3.2). You may distribute any executables you create under a license of your choosing, as long as that license does not interfere with the recipients' rights to the source under the terms of the MPL.

MPL2.0 FAQ

Yes, MPL- and Apache-licensed code can be used with an MIT codebase (so in that sense, they are "compatible"). However, the MPL- / Apache-licensed code remains under its original license. (So although compatible, you cannot relicense someone else's MPL or Apache code into the MIT license.) This means that your final codebase will contain a mix of MPL, Apache, and MIT licensed code. As an example, MPL has weak copyleft, so if you modified an MPL file, that file (including your changes) must remain under the MPL license.

Answer1

Questions about license EUPL-1.2

You should use this license if you are located in the EU which gives you more advantages over GPL because in case of any disputes, the license allows you to defend your rights in a European Union country, in this case it will be Spain. It has also been translated into all languages of the EU member states.

Matrix of EUPL compatible open source licences

EUPL-1.2 is incompatiable with GPL according to GNU ORG

This is a free software license. By itself, it has a copyleft comparable to the GPL's, and incompatible with it.

Version

V0.2.0

Changelog
  • Added mutex protected version for CPUs which does not support atomics.
  • Updated atomics code.
Changelog v0.1.1
  • Initial release

License:

Sources are available under: MPL-2.0 OR EUPL-1.2

Examples

The examples are availabe in the directory examples.

Block diagram

                     ┌───────────────────┐                                         
                     │                   │                                         
                     │     ItemOwner     │◄───────────────────────────────────────┐
                     │                   │                                        │
                     └────────┬──────────┘                                        │
                              │                                                   │
                              │                                                   │
                              │                                                   │
                              │                                                   │
                    ┌─────────▼──────────────┐                                    │
                    │                        │                                    │
                    │  transfer_ownership()  │                                    │
                    │                        │                                    │
                    └────┬──┬──┬─────────────┘                                    │
                         │  │  │                                                  │
                         │  │  │  ───────────────────────────────────────         │
                         │  │  │         EXCLUSIVE ACCESS                         │
┌──────────────────┐     │  │  │     ┌───────────────────────────┐                │
│                  │     │  │  │     │         INSTANCE          │                │
│                  ◄─────┘  │  └─────►                           │                │
│  TransferError   │        │        │    ItemOwnershipTransfer  │                │
├──────────────────┘        │        └────────────┬──────────────┘                │
│                           │                     │                               │
├── AlreadyTransfered       │                     │                               │
│                           │          ┌──────────▼─────────────┐                 │
│                           │          │     send_over_MPSC     │                 │
│                           │          └────────────────────────┘                 │
│                           │                                                     │
│                                                                                 │
└── Poisoned                ───────    ────    ─────   ──────    ───    ───       │
                                                                                  │
                              ┌─────────────┐                                     │
                              │  Thread N   │                                     │
                              └─────────────┘─────────────────────┐               │
                                      │       MPSC_RECV           │               │
                                      │                           │               │
                                      │   ItemOwnershipTransfer   │               │
                                      └────────────┬──────────────┘               │
                                                   │                              │
                                                   │                              │
                                           ┌───────▼──────────┐                   │
                                           │   as_ref()       │                   │
                                           │                  │                   │
                                           │   as_mut()       │                   │
                                           └───────┬──────────┘                   │
                                                   │                              │
                                                   │                              │
                                           ┌───────▼──────────┐                   │
                                           │   drop()         │                   │
                                           │                  ┼───────────────────┘
                                           └──────────────────┘                                                            

Usage.

Firstly, the inner item should be initialized and the Owner container should be created with the inner item.

/// The inenr type. It is not necessary that it should be in the `Box`.
let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
 
// creating new instance
let owner = ItemOwner::new(task1);

A ownership can be transfered. Like RefCell provides borrow, here an exclusive transfer can be perfromed.

let transfer: ItemOwnershipTransfer<PeriodicTaskHndl> = owner.transfer_ownership().unwrap()

The obtained ItemOwnershipTransfer can be send over the MPSC or any other way because it is Sync + Send.

    let (se, rc) = 
        mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();

    se.send(transfer);

The ownership can be returned by droppping the transfer.

    let mut task: ItemOwnershipTransfer<PeriodicTaskHndl> = rc.recv().unwrap();
    task.as_mut().exec().unwrap();

    // return the borrow
    drop(task);

The inner value can be accessed via dereferencing. In case if receiving thread panics before returning the borrowed ownership, the instance becomes poisoned (like mutex) and this status should be cleared manually.

The ItemOwnershipTransfer cannot be cloned and must never be copied to have multiple instances. it is not dsigned to handle this properly.

Example

use std::{fmt, sync::{atomic::{AtomicU32, Ordering}, mpsc}, time::Duration};

use crate::{ItemOwner, ItemOwnershipTransfer, OwnershipFlags, TransferError};

pub trait PeriodicTask: Send + Sync + fmt::Debug
{
    fn exec(&mut self) -> Result<(), String>;
    fn get_val(&self) -> u32;
}

pub type PeriodicTaskHndl = Box<dyn PeriodicTask>;

static DROP_FLAG: AtomicU32 = AtomicU32::new(0);

#[derive(Debug)]
pub struct Task1
{
    val: u32
}

impl Drop for Task1
{
    fn drop(&mut self) 
    {
        DROP_FLAG.fetch_add(1, Ordering::AcqRel);
        println!("dropped!");
    }
}

impl PeriodicTask for Task1
{
    fn get_val(&self) -> u32
    {
        return self.val;
    }

    fn exec(&mut self) -> Result<(), String> 
    {
        println!("task {} called", self.val);

        return Ok(());
    }
}

fn main()
{
    
    let task1: PeriodicTaskHndl = Box::new(Task1{ val: 2 });
    let owner = ItemOwner::new(task1);

    let (se, rc) = 
        mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();

    let thread_hndl = 
        std::thread::spawn(move || 
            {
                let mut task = rc.recv().unwrap();

                std::thread::sleep(Duration::from_secs(2));
                task.as_mut().exec().unwrap();

                return;
            }
        );


    se.send(owner.transfer_ownership().unwrap()).unwrap();

    while owner.is_owned() == false
    {
        std::thread::sleep(Duration::from_secs(1));
    }

    println!("completed round 1");

    thread_hndl.join().unwrap();

    let (se, rc) = 
        mpsc::channel::<ItemOwnershipTransfer<PeriodicTaskHndl>>();

    let thread_hndl = 
        std::thread::spawn(move || 
            {
                let mut task = rc.recv().unwrap();

                std::thread::sleep(Duration::from_secs(2));
                task.as_mut().exec().unwrap();

                return;
            }
        );

    se.send(owner.transfer_ownership().unwrap()).unwrap();

    while owner.is_owned() == false
    {
        std::thread::sleep(Duration::from_secs(1));
    }

    println!("completed round 2");

    thread_hndl.join().unwrap();


    return;
}
Commit count: 0

cargo fmt