Skip to content
This repository has been archived by the owner on Jan 25, 2024. It is now read-only.

Commit

Permalink
Allow to destroy any type of wand by id as well
Browse files Browse the repository at this point in the history
  • Loading branch information
MolotovCherry committed Mar 17, 2022
1 parent 05fa009 commit a19fa59
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 23 deletions.
14 changes: 12 additions & 2 deletions example/src/main/kotlin/com/example/cli/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fun main() {
try {
// this will obviously fail
wand.readImage("oops!")
// if you want to catch all of them, the base exception is MagickException
// if you want to catch all of them, the base exception is MagickException
} catch (e: MagickWandException) {
// handle it here
// this method will get the native exception details from ImageMagick and
Expand Down Expand Up @@ -87,10 +87,20 @@ fun main() {
// Every wand class also includes specific methods to destroy wands
MagickWand.destroyWands() // destroy all magickwands (but leaving other types alone)
val id = wand.id // get internal id of wand
MagickWand.destroyWandId(id) // destroy a specific wand by ID
MagickWand.destroyWandId(id) // destroy a specific wand by ID - it will not destroy any other kind of wand, even if the id matched
// you can also batch destroy wands with a ULongArray
MagickWand.destroyWandIds(ulongArrayOf(0u, 1u))

// of course, you can also destroy any type of wand by id as well
Magick.destroyWandId(0u)
// Or give more IDs
Magick.destroyWandIds(ulongArrayOf(0u, 1u))

// check to see if they're still valid wands
// if this property is true, then it is valid
// if it is false, then the wand was destroyed, and using it will result in an exception
println("Wand is valid? ${wand.isInitialized}")

// This will raise an exception. Why?
// One: the path doesn't exist
// Two: the wand is uninitialized cause we destroyed it!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,15 @@ class DrawingWand : Closeable {
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandIds(ids: ULongArray) {
Magick.destroyWandIds(ids, WandType.DrawingWand.id)
Magick.destroyWandIdsType(ids, WandType.DrawingWand.id)
}

/**
* Destroys a DrawingWand with a certain ID
* WARNING: DO NOT use the destroyed wand after. It is invalidated after that.
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandId(id: ULong) {
Magick.destroyWandId(id, WandType.DrawingWand.id)
Magick.destroyWandIdType(id, WandType.DrawingWand.id)
}
}

Expand All @@ -61,11 +60,13 @@ class DrawingWand : Closeable {
private var handle: Long? = null

/**
* The id of the wand
* The unique id of the wand.
* This id is guaranteed to be unique amongst ALL wands of ALL types
* (unless you overflow a ULong, then it'll wrap back around)
*/
val id: ULong
get() = _id.toULong()
private var _id: Long = 0
get() = _id
private var _id: ULong = 0u

/**
* Check to see if this is initialized with the underlying C obj.
Expand Down
21 changes: 18 additions & 3 deletions kmagick/src/main/kotlin/com/cherryleafroad/kmagick/Magick.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ object Magick : Closeable {
* WARNING: DO NOT use the destroyed wands after. They are invalidated after that.
*/
@OptIn(ExperimentalUnsignedTypes::class)
@JvmName("destroyWandIds")
internal external fun destroyWandIds(ids: ULongArray, wandType: Int)
@JvmName("destroyWandIdsType")
internal external fun destroyWandIdsType(ids: ULongArray, wandType: Int)

/**
* Destroys all wands of a certain type
Expand All @@ -94,6 +94,21 @@ object Magick : Closeable {
* Destroys a wand with a specific ID
* WARNING: DO NOT use the destroyed wand after. It is invalidated after that.
*/
@JvmName("destroyWandIdType")
internal external fun destroyWandIdType(id: ULong, wandType: Int)

/**
* Destroys any kind of wand with a specific ID
* WARNING: DO NOT use the destroyed wands after. They are invalidated after that.
*/
@JvmName("destroyWandId")
internal external fun destroyWandId(id: ULong, wandType: Int)
external fun destroyWandId(id: ULong)

/**
* Destroys any kind of wand whose id is contained in the array
* WARNING: DO NOT use the destroyed wands after. They are invalidated after that.
*/
@JvmName("destroyWandIds")
@OptIn(ExperimentalUnsignedTypes::class)
external fun destroyWandIds(ids: ULongArray)
}
14 changes: 9 additions & 5 deletions kmagick/src/main/kotlin/com/cherryleafroad/kmagick/MagickWand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,15 @@ class MagickWand : Closeable {
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandIds(ids: ULongArray) {
Magick.destroyWandIds(ids, WandType.MagickWand.id)
Magick.destroyWandIdsType(ids, WandType.MagickWand.id)
}

/**
* Destroys a MagickWand with a certain ID
* WARNING: DO NOT use the destroyed wand after. It is invalidated after that.
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandId(id: ULong) {
Magick.destroyWandId(id, WandType.MagickWand.id)
Magick.destroyWandIdType(id, WandType.MagickWand.id)
}
}

Expand All @@ -57,9 +56,14 @@ class MagickWand : Closeable {
*/
private var handle: Long? = null

/**
* The unique id of the wand.
* This id is guaranteed to be unique amongst ALL wands of ALL types
* (unless you overflow a ULong, then it'll wrap back around)
*/
val id: ULong
get() = _id.toULong()
private var _id: Long = 0
get() = _id
private var _id: ULong = 0u

/**
* Check to see if this is initialized with the underlying C obj.
Expand Down
14 changes: 9 additions & 5 deletions kmagick/src/main/kotlin/com/cherryleafroad/kmagick/PixelWand.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,15 @@ class PixelWand : Closeable {
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandIds(ids: ULongArray) {
Magick.destroyWandIds(ids, WandType.PixelWand.id)
Magick.destroyWandIdsType(ids, WandType.PixelWand.id)
}

/**
* Destroys a PixelWand with a certain ID
* WARNING: DO NOT use the destroyed wand after. It is invalidated after that.
*/
@OptIn(ExperimentalUnsignedTypes::class)
fun destroyWandId(id: ULong) {
Magick.destroyWandId(id, WandType.PixelWand.id)
Magick.destroyWandIdType(id, WandType.PixelWand.id)
}
}

Expand All @@ -62,9 +61,14 @@ class PixelWand : Closeable {
*/
private var handle: Long? = null

/**
* The unique id of the wand.
* This id is guaranteed to be unique amongst ALL wands of ALL types
* (unless you overflow a ULong, then it'll wrap back around)
*/
val id: ULong
get() = _id.toULong()
private var _id: Long = 0
get() = _id
private var _id: ULong = 0u

/**
* Check to see if this is initialized with the underlying C obj.
Expand Down
35 changes: 35 additions & 0 deletions rust/kmagick/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,38 @@ pub fn remove<W>(env: JNIEnv, cache: &'static Mutex<FxHashMap<u64, GlobalRef>>,
TakeObj!(env, W, cache, id);
let _ = cache.remove(&id);
}

// clear id from ANY cache
pub fn clearById(env: JNIEnv, id: &u64) -> crate::Result<()> {
let pixel_cache = &mut *PIXELWAND_CACHE.lock()?;
let magick_cache = &mut *MAGICKWAND_CACHE.lock()?;
let drawing_cache = &mut *DRAWINGWAND_CACHE.lock()?;

TakeObj!(env, PixelWand, pixel_cache, id);
TakeObj!(env, DrawingWand, drawing_cache, id);
TakeObj!(env, MagickWand, magick_cache, id);

let _ = pixel_cache.remove(id);
let _ = drawing_cache.remove(id);
let _ = magick_cache.remove(id);

Ok(())
}

// clear Ids from ANY cache
pub fn clearByIds(env: JNIEnv, ids: &[u64]) -> crate::Result<()> {
let pixel_cache = &mut *PIXELWAND_CACHE.lock()?;
let magick_cache = &mut *MAGICKWAND_CACHE.lock()?;
let drawing_cache = &mut *DRAWINGWAND_CACHE.lock()?;

for id in ids {
TakeObj!(env, PixelWand, pixel_cache, id);
TakeObj!(env, DrawingWand, drawing_cache, id);
TakeObj!(env, MagickWand, magick_cache, id);
let _ = pixel_cache.remove(id);
let _ = drawing_cache.remove(id);
let _ = magick_cache.remove(id);
}

Ok(())
}
28 changes: 26 additions & 2 deletions rust/kmagick/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ impl Magick {

// destroy a specific cache
#[jstatic]
fn destroyWandIds(env: JNIEnv, _: JObject, id_list: jlongArray, cache_type: jint) -> JNIResult<()> {
fn destroyWandIdsType(env: JNIEnv, _: JObject, id_list: jlongArray, cache_type: jint) -> JNIResult<()> {
let id_list = env.get_long_array_elements(id_list, ReleaseMode::NoCopyBack)?;

let len = id_list.size()? as usize;
Expand Down Expand Up @@ -223,7 +223,7 @@ impl Magick {
}

#[jstatic]
fn destroyWandId(env: JNIEnv, _: JObject, id: jlong, cache_type: jint) {
fn destroyWandIdType(env: JNIEnv, _: JObject, id: jlong, cache_type: jint) {
let id = bytemuck::cast::<jlong, u64>(id);

let cache_type = CacheType::n(cache_type).unwrap();
Expand All @@ -246,6 +246,30 @@ impl Magick {
};
}

#[jstatic]
fn destroyWandId(env: JNIEnv, _: JObject, id: jlong) -> JNIResult<()> {
let id = bytemuck::cast::<jlong, u64>(id);
cache::clearById(env, &id)?;
Ok(())
}

#[jstatic]
fn destroyWandIds(env: JNIEnv, _: JObject, id_list: jlongArray) -> JNIResult<()> {
let id_list = env.get_long_array_elements(id_list, ReleaseMode::NoCopyBack)?;

let len = id_list.size()? as usize;
let slice = unsafe {
std::slice::from_raw_parts(id_list.as_ptr(), len)
};

// kotlin bytecode ULong is actually a J. Perfect! Translates 100% to u64
let slice = bytemuck::cast_slice::<jlong, u64>(slice);

cache::clearByIds(env, slice)?;

Ok(())
}

#[jignore]
fn isMagickWandInstantiated() -> bool {
unsafe {
Expand Down

0 comments on commit a19fa59

Please sign in to comment.