Browse Source
High Priority Fixes: - Fix thread pool management: Add shared preprocessingExecutor to prevent creating new thread pools per detection - Add proper thread pool shutdown with grace period in cleanup() method - Remove memory leak from repeated Executors.newFixedThreadPool() calls Code Quality Infrastructure: - Add MatUtils.kt with safe Mat resource management extension functions - Add MLResult.kt with standardized error handling for ML operations - Prepare foundation for systematic error handling improvements Performance Impact: - Eliminates thread pool creation overhead during inference - Reduces memory pressure from abandoned thread pools - Maintains all original ML detection functionality 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>arch-002-ml-inference-engine
3 changed files with 163 additions and 9 deletions
@ -0,0 +1,83 @@ |
|||||
|
package com.quillstudios.pokegoalshelper.ml |
||||
|
|
||||
|
/** |
||||
|
* Result wrapper for ML operations to standardize error handling |
||||
|
*/ |
||||
|
sealed class MLResult<out T> |
||||
|
{ |
||||
|
data class Success<T>(val data: T) : MLResult<T>() |
||||
|
data class Error(val exception: Throwable, val message: String) : MLResult<Nothing>() |
||||
|
|
||||
|
/** |
||||
|
* Returns the data if successful, or null if error |
||||
|
*/ |
||||
|
fun getOrNull(): T? = when (this) |
||||
|
{ |
||||
|
is Success -> data |
||||
|
is Error -> null |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Returns the data if successful, or the default value if error |
||||
|
*/ |
||||
|
fun getOrDefault(default: T): T = when (this) |
||||
|
{ |
||||
|
is Success -> data |
||||
|
is Error -> default |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute block if successful |
||||
|
*/ |
||||
|
inline fun onSuccess(block: (T) -> Unit): MLResult<T> |
||||
|
{ |
||||
|
if (this is Success) block(data) |
||||
|
return this |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute block if error |
||||
|
*/ |
||||
|
inline fun onError(block: (Throwable, String) -> Unit): MLResult<T> |
||||
|
{ |
||||
|
if (this is Error) block(exception, message) |
||||
|
return this |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Transform the data if successful |
||||
|
*/ |
||||
|
inline fun <R> map(transform: (T) -> R): MLResult<R> = when (this) |
||||
|
{ |
||||
|
is Success -> try { Success(transform(data)) } |
||||
|
catch (e: Exception) { Error(e, "Transform failed: ${e.message}") } |
||||
|
is Error -> this |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Helper functions for creating results |
||||
|
*/ |
||||
|
inline fun <T> mlTry(operation: () -> T): MLResult<T> |
||||
|
{ |
||||
|
return try |
||||
|
{ |
||||
|
MLResult.Success(operation()) |
||||
|
} |
||||
|
catch (e: Exception) |
||||
|
{ |
||||
|
MLResult.Error(e, "Operation failed: ${e.message}") |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
inline fun <T> mlTryWithMessage(message: String, operation: () -> T): MLResult<T> |
||||
|
{ |
||||
|
return try |
||||
|
{ |
||||
|
MLResult.Success(operation()) |
||||
|
} |
||||
|
catch (e: Exception) |
||||
|
{ |
||||
|
MLResult.Error(e, "$message: ${e.message}") |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
package com.quillstudios.pokegoalshelper.ml |
||||
|
|
||||
|
import org.opencv.core.Mat |
||||
|
|
||||
|
/** |
||||
|
* Utility functions for safe Mat resource management |
||||
|
*/ |
||||
|
|
||||
|
/** |
||||
|
* Execute a block with automatic Mat cleanup |
||||
|
*/ |
||||
|
inline fun <T> Mat.use(block: (Mat) -> T): T |
||||
|
{ |
||||
|
return try |
||||
|
{ |
||||
|
block(this) |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
this.release() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Execute a block with multiple Mats and automatic cleanup |
||||
|
*/ |
||||
|
inline fun <T> useMats(vararg mats: Mat, block: () -> T): T |
||||
|
{ |
||||
|
return try |
||||
|
{ |
||||
|
block() |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
mats.forEach { it.release() } |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Create a new Mat and execute block with automatic cleanup |
||||
|
*/ |
||||
|
inline fun <T> withNewMat(block: (Mat) -> T): T |
||||
|
{ |
||||
|
return Mat().use(block) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Create multiple new Mats and execute block with automatic cleanup |
||||
|
*/ |
||||
|
inline fun <T> withNewMats(count: Int, block: (List<Mat>) -> T): T |
||||
|
{ |
||||
|
val mats = (1..count).map { Mat() } |
||||
|
return try |
||||
|
{ |
||||
|
block(mats) |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
mats.forEach { it.release() } |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue