Skip to content

Commit

Permalink
Provide multiple ways to install Jlrs.jl
Browse files Browse the repository at this point in the history
  • Loading branch information
Taaitaaiger committed Apr 21, 2023
1 parent 1b1664f commit a0e4240
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 95 deletions.
1 change: 1 addition & 0 deletions jl_sys/generate_bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ function print_help() {
echo ""
echo " apt install llvm-dev libclang-dev clang g++-multilib-i686-linux-gnu"
echo " rustup target add i686-unknown-linux-gnu"
echo " rustup toolchain install nightly"
echo " rustup toolchain install stable-i686-unknown-linux-gnu"
}

Expand Down
2 changes: 1 addition & 1 deletion jl_sys/src/bindings/bindings_1_10_32.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* generated from julia version 1.10.0-DEV (Commit: 844c20dd63 2023-04-10 17:50 UTC) */
/* generated from julia version 1.10.0-DEV (Commit: ff7b8eb00b 2023-04-14 16:29 UTC) */
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
Expand Down
2 changes: 1 addition & 1 deletion jl_sys/src/bindings/bindings_1_10_64.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* generated from julia version 1.10.0-DEV (Commit: 844c20dd63 2023-04-10 17:50 UTC) */
/* generated from julia version 1.10.0-DEV (Commit: ff7b8eb00b 2023-04-14 16:29 UTC) */
#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
Expand Down
3 changes: 2 additions & 1 deletion jlrs/src/ccall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use crate::{
target::{frame::GcFrame, unrooted::Unrooted, Target},
},
private::Private,
InstallJlrs,
};

// The pool is lazily created either when it's first used, or when the number of threads is set.
Expand Down Expand Up @@ -258,7 +259,7 @@ impl<'context> CCall<'context> {
/// A module can be provided to allow setting the size of the internal thread pool from Julia
/// by calling `Jlrs.set_pool_size`.
#[inline(never)]
pub fn init_jlrs(&mut self, install_jlrs_jl: bool, module: Option<Module>) {
pub fn init_jlrs(&mut self, install_jlrs_jl: &InstallJlrs, module: Option<Module>) {
unsafe {
init_jlrs(&mut self.frame, install_jlrs_jl);

Expand Down
64 changes: 16 additions & 48 deletions jlrs/src/data/types/foreign_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,14 @@
//! `julia_module` automatically takes care of this, otherwise you must manually call
//! `OpaqueType::create_type` or `OpaqueType::reinit_type`. The first must be called if the
//! type doesn't exist yet, the second if the module that defines the type has been precompiled.
use std::{
any::TypeId,
ffi::c_void,
mem::MaybeUninit,
ptr::NonNull,
sync::{Arc, RwLock},
};
use std::{any::TypeId, ffi::c_void, mem::MaybeUninit, ptr::NonNull, sync::RwLock};

#[julia_version(except = ["1.7"])]
use jl_sys::jl_gc_schedule_foreign_sweepfunc;
#[julia_version(since = "1.9")]
use jl_sys::jl_reinit_foreign_type;
use jl_sys::{jl_emptysvec, jl_gc_alloc_typed, jl_new_datatype, jl_new_foreign_type, jl_value_t};
use jlrs_macros::julia_version;
use once_cell::sync::OnceCell;

use super::typecheck::Typecheck;
use crate::{
Expand All @@ -91,21 +84,19 @@ use crate::{
private::Private,
};

static FOREIGN_TYPE_REGISTRY: OnceCell<Arc<ForeignTypes>> = OnceCell::new();

pub(crate) unsafe extern "C" fn init_foreign_type_registry() {
FOREIGN_TYPE_REGISTRY.get_or_init(|| {
Arc::new(ForeignTypes {
data: RwLock::new(Vec::new()),
})
});
}
static FOREIGN_TYPE_REGISTRY: ForeignTypes = ForeignTypes::new();

struct ForeignTypes {
data: RwLock<Vec<(TypeId, DataType<'static>)>>,
}

impl ForeignTypes {
const fn new() -> Self {
ForeignTypes {
data: RwLock::new(Vec::new()),
}
}

fn find<T: 'static>(&self) -> Option<DataType> {
let tid = TypeId::of::<T>();
self.data
Expand Down Expand Up @@ -286,7 +277,7 @@ where
U: ForeignType,
T: Target<'target>,
{
if let Some(ty) = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<U>() {
if let Some(ty) = FOREIGN_TYPE_REGISTRY.find::<U>() {
return target.data_from_ptr(ty.unwrap_non_null(Private), Private);
}

Expand Down Expand Up @@ -315,8 +306,6 @@ where

debug_assert!(!ty.is_null());
FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.data
.write()
.expect("Foreign type lock was poisoned")
Expand All @@ -337,7 +326,7 @@ where
U: OpaqueType,
T: Target<'target>,
{
if let Some(ty) = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<U>() {
if let Some(ty) = FOREIGN_TYPE_REGISTRY.find::<U>() {
return target.data_from_ptr(ty.unwrap_non_null(Private), Private);
}

Expand Down Expand Up @@ -372,8 +361,6 @@ where

debug_assert!(!ty.is_null());
FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.data
.write()
.expect("Foreign type lock was poisoned")
Expand Down Expand Up @@ -425,7 +412,7 @@ unsafe fn reinit_foreign_type<U>(datatype: DataType) -> bool
where
U: ForeignType,
{
if let Some(_) = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<U>() {
if let Some(_) = FOREIGN_TYPE_REGISTRY.find::<U>() {
return true;
}

Expand All @@ -441,8 +428,6 @@ where
let ret = jl_reinit_foreign_type(ty, Some(mark::<U>), Some(sweep::<U>));
if ret != 0 {
FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.data
.write()
.expect("Foreign type lock was poisoned")
Expand All @@ -468,13 +453,11 @@ unsafe fn reinit_opaque_type<U>(ty: DataType) -> bool
where
U: OpaqueType,
{
if let Some(_) = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<U>() {
if let Some(_) = FOREIGN_TYPE_REGISTRY.find::<U>() {
return true;
}

FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.data
.write()
.expect("Foreign type lock was poisoned")
Expand Down Expand Up @@ -508,11 +491,7 @@ unsafe impl<F: OpaqueType> IntoJulia for F {
where
T: Target<'scope>,
{
let ty = FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.find::<F>()
.expect("Doesn't exist");
let ty = FOREIGN_TYPE_REGISTRY.find::<F>().expect("Doesn't exist");
unsafe { target.data_from_ptr(ty.unwrap_non_null(Private), Private) }
}

Expand All @@ -523,14 +502,12 @@ unsafe impl<F: OpaqueType> IntoJulia for F {
unsafe {
let ptls = get_tls();
let sz = std::mem::size_of::<Self>();
let maybe_ty = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<F>();
let maybe_ty = FOREIGN_TYPE_REGISTRY.find::<F>();

let ty = match maybe_ty {
None => {
if let Some(func) = Self::TYPE_FN {
let mut guard = FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.data
.write()
.expect("Foreign type lock was poisoned");
Expand Down Expand Up @@ -584,7 +561,7 @@ unsafe impl<F: OpaqueType> IntoJulia for F {
unsafe impl<T: OpaqueType> ValidLayout for T {
fn valid_layout(ty: Value) -> bool {
if let Ok(dt) = ty.cast::<DataType>() {
if let Some(ty) = FOREIGN_TYPE_REGISTRY.get().unwrap().find::<T>() {
if let Some(ty) = FOREIGN_TYPE_REGISTRY.find::<T>() {
dt.unwrap(Private) == ty.unwrap(Private)
} else {
false
Expand Down Expand Up @@ -625,8 +602,6 @@ unsafe impl<T: OpaqueType> ConstructType for T {
{
let (target, _) = target.split();
FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.find::<T>()
.unwrap()
.as_value()
Expand All @@ -637,13 +612,6 @@ unsafe impl<T: OpaqueType> ConstructType for T {
where
Tgt: Target<'target>,
{
Some(
FOREIGN_TYPE_REGISTRY
.get()
.unwrap()
.find::<T>()
.unwrap()
.as_value(),
)
Some(FOREIGN_TYPE_REGISTRY.find::<T>().unwrap().as_value())
}
}
135 changes: 101 additions & 34 deletions jlrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,22 +761,20 @@
//! [`julia_module`]: jlrs_macros::julia_module
//! [documentation]: jlrs_macros::julia_module
//! [rustfft_jl]: https://github.com/Taaitaaiger/rustfft-jl
//! [here]: https://github.com/JuliaPackaging/Yggdrasil/tree/master/R/rustfft-jl
//! [here]: https://github.com/JuliaPackaging/Yggdrasil/tree/master/R/rustfft_jl
#![forbid(rustdoc::broken_intra_doc_links)]

use std::sync::atomic::AtomicBool;
use std::sync::atomic::{AtomicBool, Ordering};

use atomic::Ordering;
use memory::stack_frame::PinnedFrame;
#[cfg(feature = "sync-rt")]
use once_cell::sync::OnceCell;

use crate::{
data::{
managed::{module::Module, value::Value},
types::foreign_type::init_foreign_type_registry,
},
data::managed::{module::Module, value::Value},
memory::{
context::{ledger::init_ledger, stack::Stack},
stack_frame::PinnedFrame,
target::unrooted::Unrooted,
},
};
Expand Down Expand Up @@ -827,36 +825,108 @@ pub mod safety;
#[cfg(feature = "sync-rt")]
pub mod util;

pub(crate) unsafe fn init_jlrs<const N: usize>(frame: &mut PinnedFrame<N>, install_jlrs_jl: bool) {
/// Installation method for the Jlrs package. If Jlrs is already installed the installed version
/// is used.
#[derive(Clone)]
pub enum InstallJlrs {
/// Install the current default revision of Jlrs.jl
Default,
/// Don't install the Jlrs package
No,
/// Install the given version
Version {
/// Major version
major: usize,
/// Minor version
minor: usize,
/// Patch version
patch: usize,
},
/// Install a revision of some git repository
Git {
/// URL of the repository
repo: String,
/// Revision to be installed
revision: String,
},
}

impl InstallJlrs {
pub(crate) unsafe fn use_or_install(&self, unrooted: Unrooted) {
match self {
InstallJlrs::Default => {
Value::eval_string(
unrooted,
"if !isdefined(Main, :Jlrs)
try
using Jlrs
catch e
import Pkg; Pkg.add(url=\"https://github.com/Taaitaaiger/Jlrs.jl#f88969f\")
using Jlrs
end
end",
)
},
InstallJlrs::Git { repo, revision } => {
Value::eval_string(
unrooted,
format!(
"if !isdefined(Main, :Jlrs)
try
using Jlrs
catch e
import Pkg; Pkg.add(url=\"{repo}#{revision}\")
using Jlrs
end
end"
),
)
},
InstallJlrs::Version { major, minor, patch } => {
Value::eval_string(
unrooted,
format!(
"if !isdefined(Main, :Jlrs)
try
using Jlrs
catch e
import Pkg; Pkg.add(name=\"Jlrs\", version=\"{major}.{minor}.{patch}\")
using Jlrs
end
end"
),
)
},
InstallJlrs::No => {
Value::eval_string(
unrooted,
"if !isdefined(Main, :Jlrs)
using Jlrs
end",
)
},
}
.expect("Failed to load or install Jlrs package");
}
}

// The chosen install method is stored in a OnceCell when the sync runtime is used to
// avoid having to store it in `PendingJulia`.
#[cfg(feature = "sync-rt")]
pub(crate) static INSTALL_METHOD: OnceCell<InstallJlrs> = OnceCell::new();

pub(crate) unsafe fn init_jlrs<const N: usize>(
frame: &mut PinnedFrame<N>,
install_jlrs_jl: &InstallJlrs,
) {
static IS_INIT: AtomicBool = AtomicBool::new(false);

if IS_INIT.swap(true, Ordering::Relaxed) {
return;
}

let unrooted = Unrooted::new();
if install_jlrs_jl {
Value::eval_string(
unrooted,
"if !isdefined(Main, :Jlrs)
try
using Jlrs
catch e
import Pkg; Pkg.add(url=\"https://github.com/Taaitaaiger/Jlrs.jl\")
using Jlrs
end
end",
)
.expect("Failed to load or install Jlrs package");
} else {
Value::eval_string(
unrooted,
"if !isdefined(Main, :Jlrs)
using Jlrs
end",
)
.expect("Failed to load or install Jlrs package");
}
install_jlrs_jl.use_or_install(unrooted);

let jlrs_module = Module::main(&unrooted)
.submodule(unrooted, "Jlrs")
Expand All @@ -865,9 +935,6 @@ pub(crate) unsafe fn init_jlrs<const N: usize>(frame: &mut PinnedFrame<N>, insta

init_ledger();

// Init foreign type registry
init_foreign_type_registry();

// Init foreign Stack type
Stack::init(frame, jlrs_module);
}
2 changes: 1 addition & 1 deletion jlrs/src/runtime/async_rt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ where
let base_frame: &'static mut StackFrame<N> = std::mem::transmute(base_frame);
let mut pinned = base_frame.pin();

init_jlrs(&mut pinned, builder.builder.install_jlrs_jl);
init_jlrs(&mut pinned, &builder.builder.install_jlrs_jl);

let base_frame = pinned.stack_frame();

Expand Down
Loading

0 comments on commit a0e4240

Please sign in to comment.