core-foundation-rs icon indicating copy to clipboard operation
core-foundation-rs copied to clipboard

Encode retaining and releasing in types

Open nox opened this issue 9 years ago • 7 comments

This is an idea I'm thinking about these days, we should be able to not retain things when using the get rule, instead we should be able to rely on lifetimes.

use std::ops::{Deref, Drop};

pub trait Release {
    unsafe fn release(&self);
}

pub struct Retained<T>(T) where T: Release;

impl<T: Release> Drop for Retained<T> {
    fn drop(&mut self) {
        unsafe {
            self.0.release();
        }
    }
}

enum Opaque {}
pub struct CFURL(Opaque);
pub struct CFURLRef(*const CFURL);

impl Release for CFURLRef {
    unsafe fn release(&self) {
        ...
    }
}

impl Deref for CFURLRef {
    type Target = CFURL;

    fn deref(&self) -> &CFURL {
        unsafe { &*self.0 }
    }
}

With additional traits for casting to supertype CFTypeRef, we should be able to provide functions going from &CFString to Retained<CFStringRef>.

nox avatar Sep 01 '16 11:09 nox

So I've realised we can encode things in a way simpler fashion:

use std::ops::{Deref, Drop};

pub trait Release {
    unsafe fn release(&self);
}

pub struct Rc<T: Release>(*mut T);

impl<T: Release> Deref for Rc<T> {
    type Target = T;

    fn deref(&self) -> &T {
        unsafe { &*self.0 }
    }
}

impl<T: Release> Drop for Rc<T> {
    fn drop(&mut self) {
        unsafe {
            (&mut *self.0).release();
        }
    }
}

enum Opaque {}
pub struct CFURL(Opaque);

impl Release for CFURL {
    unsafe fn release(&self) {
        ...
    }
}

Should I go ahead with this? I don't like the current situation, it's kinda like rust-mozjs but worse, because many things here are marked as safe even though they are just passed raw pointers.

Cc @metajack.

nox avatar Sep 06 '16 11:09 nox

Cc @sfackler who wrote rust-security-framework and @dtwood who wrote core-midi-rs.

nox avatar Sep 06 '16 12:09 nox

I recently overhauled rust-openssl to do this kind of thing, though with separate Foo and FooRef<'a> types rather than a type parameter: e.g. http://sfackler.github.io/rust-openssl/doc/v0.8.2/openssl/asn1/index.html

sfackler avatar Sep 06 '16 15:09 sfackler

There are some other breaking changes I'd like to make to core-foundation-rs, so give me a heads up if you're preparing for a breaking release.

sfackler avatar Sep 06 '16 15:09 sfackler

@sfackler I think it would be easier to have a type representing the refcounted things from CF, rather than 2 separate types for each. That would allow us to have a Unique<T: Release> wrapper of some sort, for CFMutableArray and friends.

nox avatar Sep 06 '16 15:09 nox

Yeah, that sounds like a reasonable approach.

sfackler avatar Sep 06 '16 16:09 sfackler

@sfackler I also have some neat ideas in mind, like CFString<'a> which would allow us to transparently make a CFString<'a> from a &'a str; will start doing that this week.

nox avatar Sep 06 '16 16:09 nox