Merge branch 'rust': Wrong branch, whoops.

master
Avril 2 years ago
commit 671fcd3968
Signed by: flanchan
GPG Key ID: 284488987C31F630

2
.gitignore vendored

@ -4,3 +4,5 @@ cow-*
obj/ obj/
*~ *~
vgcore.* vgcore.*
target/
!cowslice/*.a

@ -5,7 +5,7 @@ PROJECT=cow
AUTHOR=Avril (Flanchan) <flanchan@cumallover.me> AUTHOR=Avril (Flanchan) <flanchan@cumallover.me>
VERSION_MAJOR=0 VERSION_MAJOR=0
VERSION_MINOR=2.0 VERSION_MINOR=3.0
VERSION=$(VERSION_MAJOR).$(VERSION_MINOR) VERSION=$(VERSION_MAJOR).$(VERSION_MINOR)
ifeq ($(PREFIX),) ifeq ($(PREFIX),)

34
cowslice/Cargo.lock generated

@ -0,0 +1,34 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "cowslice"
version = "0.1.0"
dependencies = [
"rustc_version",
]
[[package]]
name = "rustc_version"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
dependencies = [
"semver",
]
[[package]]
name = "semver"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
dependencies = [
"semver-parser",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"

@ -0,0 +1,11 @@
[package]
name = "cowslice"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[build-dependencies]
rustc_version = "0.2"

@ -0,0 +1,27 @@
extern crate rustc_version;
use rustc_version::{version, version_meta, Channel};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
Channel::Stable => {
println!("cargo:rustc-cfg=stable");
}
Channel::Beta => {
println!("cargo:rustc-cfg=beta");
}
Channel::Nightly => {
println!("cargo:rustc-cfg=nightly");
}
Channel::Dev => {
println!("cargo:rustc-cfg=dev");
}
}
// Link to `libcow.a`
println!(r"cargo:rustc-link-search=./lib");
println!(r"cargo:rustc-link-lib=cow");
}

@ -0,0 +1,41 @@
use super::*;
use std::{error, fmt};
use std::ffi::CStr;
/// A `libcow` error object.
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Error(i32);
impl Error
{
/// The last error in `libcow`.
#[inline(always)] pub fn last() -> Self
{
Self(unsafe {ffi::cow_err()})
}
}
impl error::Error for Error{}
impl fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
const DEFAULT: &'static [u8] = b"unknown\0"; // must be `nul`'d
let cstr = unsafe {
let ptr = ffi::cow_err_msg(self.0);
if ptr.is_null() {
CStr::from_bytes_with_nul_unchecked(DEFAULT)
} else {
let ptr = *ptr;
if ptr.is_null() {
CStr::from_bytes_with_nul_unchecked(DEFAULT)
} else {
CStr::from_ptr(ptr as *const i8)
}
}
};
write!(f, "{}", cstr.to_string_lossy())
}
}

@ -0,0 +1,29 @@
//! Interfaces with the C library
use core::ffi::c_void;
/// Raw `cow_t*`
///
/// This is, essentially, a pointer to the origin (`void*`) pointer.
/// So is represented as `*mut RawHandle == void**`.
pub type RawHandle = *mut c_void;
extern "C" {
pub fn cow_create(sz: usize) -> *mut RawHandle;
pub fn cow_free(cow: *mut RawHandle);
pub fn cow_clone(cow: *const RawHandle) -> *mut RawHandle;
pub fn cow_is_fake(cow: *const RawHandle) -> i32;
pub fn cow_size(cow: *const RawHandle) -> usize;
pub fn cow_err() -> i32;
pub fn cow_err_msg(kind: i32) -> *const *const u8;
}
#[inline(always)] pub unsafe fn cow_area_mut(cow: *mut RawHandle) -> *mut c_void
{
*cow
}
#[inline(always)] pub unsafe fn cow_area(cow: *const RawHandle) -> *const c_void
{
(*cow) as *const _
}

@ -0,0 +1,23 @@
#![allow(dead_code)]
mod ffi;
pub mod error;
pub use error::Error;
#[cfg(test)]
mod tests {
#[test]
fn link_works() {
unsafe {
let raw_h = super::ffi::cow_create(100);
assert_ne!(raw_h as usize, 0);
println!("Raw handle pointer is {:p}", raw_h);
super::ffi::cow_free(raw_h);
}
unsafe {
assert_eq!(super::ffi::cow_err(), 1, "There was an error in `cow_free`");
}
}
}

@ -35,6 +35,13 @@ typedef struct cow_mapped_slice cow_t;
/// Writes to this instance pointer (`cow_ptr()`) are written to the allocated memory. /// Writes to this instance pointer (`cow_ptr()`) are written to the allocated memory.
/// Writes to any cloned instances do not propagate to this instance. /// Writes to any cloned instances do not propagate to this instance.
cow_t* cow_create(size_t size); cow_t* cow_create(size_t size);
/// Create a new copy-on-write area of `size` bytes from file `fd`.
/// Writes to this instance pointer (`cow_ptr()`) are written to the allocated memory.
/// Writes to any cloned instances do not propagate to this instance.
///
/// The resulting object does not own `fd`, but does own a duplicate of it.
cow_t* cow_create_fd(int fd, size_t size);
/// Free a cow area. This should be called on all clones before the parent of those clones is freed. /// Free a cow area. This should be called on all clones before the parent of those clones is freed.
void cow_free(cow_t* restrict cow); void cow_free(cow_t* restrict cow);
/// Create a clone of this instance. Any writes to the returned pointer will not be propagated to the input one. /// Create a clone of this instance. Any writes to the returned pointer will not be propagated to the input one.

@ -21,7 +21,9 @@ struct Cow : public _cow_util::Span<unsigned char> {
struct Fake; struct Fake;
Cow() = delete; Cow() = delete;
Cow(int fd, size_t size);
explicit Cow(size_t size); explicit Cow(size_t size);
Cow(Cow&& m); Cow(Cow&& m);
virtual ~Cow(); virtual ~Cow();

@ -76,13 +76,13 @@ size_t cow_size(const cow_t* cow)
return cow->size; return cow->size;
} }
inline internal cow_t _cow_create_unboxed(size_t size) inline internal cow_t _cow_create_unboxed(int _fd, size_t size)
{ {
cow_t ret; cow_t ret;
ret.size = size; ret.size = size;
if( (ret.poisoned = if( (ret.poisoned =
((ret.fd = shm_fd(size)) == -1)) ((ret.fd = _fd < 0 ? shm_fd(size) : _fd) == -1))
) { ) {
ret.origin = NULL; ret.origin = NULL;
return ret; return ret;
@ -96,7 +96,14 @@ inline internal cow_t _cow_create_unboxed(size_t size)
} }
cow_t* cow_create(size_t size) cow_t* cow_create(size_t size)
{ {
return box_value(_cow_create_unboxed(size)); return box_value(_cow_create_unboxed(-1, size));
}
cow_t* cow_create_fd(int fd, size_t size)
{
fd = dup(fd);
if(__builtin_expect(fd < 0, false)) return NULL;
return box_value(_cow_create_unboxed(fd, size));
} }
inline internal void _cow_free_unboxed(const cow_t* cow) inline internal void _cow_free_unboxed(const cow_t* cow)

@ -15,6 +15,7 @@ struct Cow::_inner {
~_inner(); ~_inner();
_inner(size_t sz); _inner(size_t sz);
_inner(int fd, size_t sz);
_inner(cow_t* ptr); _inner(cow_t* ptr);
_inner(const _inner& copy) = delete; _inner(const _inner& copy) = delete;
@ -27,10 +28,12 @@ Cow::_inner::~_inner() {
_cow_free_unboxed(ptr()); _cow_free_unboxed(ptr());
cow.poisoned=true; cow.poisoned=true;
} }
Cow::_inner::_inner(size_t sz) : cow(_cow_create_unboxed(sz)){ Cow::_inner::_inner(int fd, size_t sz) : cow(_cow_create_unboxed(fd, sz)){
if(UNLIKELY(cow.poisoned)) throw CowException(cow_err()); if(UNLIKELY(cow.poisoned)) throw CowException(cow_err());
} }
Cow::_inner::_inner(size_t sz) : _inner(-1, sz) {}
Cow::_inner::_inner(cow_t* ptr) : cow(*ptr) Cow::_inner::_inner(cow_t* ptr) : cow(*ptr)
{ {
free(ptr); free(ptr);
@ -38,6 +41,7 @@ Cow::_inner::_inner(cow_t* ptr) : cow(*ptr)
} }
Cow::Cow(size_t size) : super(std::make_shared<_inner>(size)){} Cow::Cow(size_t size) : super(std::make_shared<_inner>(size)){}
Cow::Cow(int fd, size_t size) : super(std::make_shared<_inner>(fd, size)){}
Cow::Cow(cow_t* raw) : super(std::make_shared<_inner>(raw)){} Cow::Cow(cow_t* raw) : super(std::make_shared<_inner>(raw)){}
Cow::Cow(Cow&& m) : super(std::move(*const_cast<std::shared_ptr<_inner>*>(&m.super))){} Cow::Cow(Cow&& m) : super(std::move(*const_cast<std::shared_ptr<_inner>*>(&m.super))){}

@ -44,7 +44,7 @@ _Static_assert
(offsetof(cow_t, size) == sizeof(void*), "`cow_t.size` should have an offset equal to `sizeof(void*)` or cow_size_unsafe() becomes UB."); (offsetof(cow_t, size) == sizeof(void*), "`cow_t.size` should have an offset equal to `sizeof(void*)` or cow_size_unsafe() becomes UB.");
#endif #endif
cow_t _cow_create_unboxed(size_t size) internal; cow_t _cow_create_unboxed(int rfd, size_t size) internal;
void _cow_free_unboxed(const cow_t* cow) internal; void _cow_free_unboxed(const cow_t* cow) internal;
#ifdef __cplusplus #ifdef __cplusplus

Loading…
Cancel
Save