#![allow(missing_docs)]
use super::{Effect};
use crate::eval::value::{ThreadSafeEnvironment, Value, Generation};
use std::collections::{HashMap, VecDeque};
use std::fmt;
use std::sync::{Arc, Weak, RwLock};
use std::sync::atomic::{AtomicU64, Ordering};
static GENERATION_COUNTER: AtomicU64 = AtomicU64::new(1);
fn next_generation() -> Generation {
GENERATION_COUNTER.fetch_add(1, Ordering::SeqCst)
}
#[derive(Debug, Clone)]
pub struct GenerationalEnvManager {
current_generation: Generation,
generation_history: VecDeque<GenerationRecord>,
max_history: usize,
environment_registry: Arc<RwLock<HashMap<Generation, Vec<Weak<GenerationalEnvironment>>>>>,
}
#[derive(Debug, Clone)]
pub struct GenerationRecord {
generation: Generation,
env_count: usize,
causing_effects: Vec<Effect>,
#[allow(dead_code)]
created_at: std::time::Instant,
#[allow(dead_code)]
parent_generation: Option<Generation>,
}
#[derive(Debug)]
pub struct GenerationalEnvironment {
inner: Arc<ThreadSafeEnvironment>,
generation: Generation,
parent: Option<Arc<GenerationalEnvironment>>,
manager: GenerationalEnvManager,
}
#[derive(Debug, Clone)]
pub struct GenerationalConfig {
pub max_history: usize,
pub auto_cleanup: bool,
pub cleanup_threshold: usize,
pub track_stats: bool,
}
#[derive(Debug, Clone)]
pub struct GenerationStats {
pub total_generations: u64,
pub active_generations: usize,
pub current_env_count: usize,
pub estimated_memory_kb: usize,
}
impl GenerationalEnvManager {
pub fn new() -> Self {
Self {
current_generation: 0,
generation_history: VecDeque::new(),
max_history: 100, environment_registry: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn with_config(config: GenerationalConfig) -> Self {
Self {
current_generation: 0,
generation_history: VecDeque::new(),
max_history: config.max_history,
environment_registry: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn current_generation(&self) -> Generation {
self.current_generation
}
pub fn new_generation(&mut self, effects: Vec<Effect>) -> Generation {
let new_gen = next_generation();
let record = GenerationRecord {
generation: new_gen,
env_count: 0,
causing_effects: effects,
created_at: std::time::Instant::now(),
parent_generation: if self.current_generation == 0 {
None
} else {
Some(self.current_generation)
},
};
self.generation_history.push_back(record);
if self.generation_history.len() > self.max_history {
self.cleanup_old_generations();
}
self.current_generation = new_gen;
new_gen
}
pub fn create_environment(
&mut self,
parent: Option<Arc<ThreadSafeEnvironment>>,
effects: Vec<Effect>
) -> Arc<GenerationalEnvironment> {
let generation = if effects.iter().any(|e| e.is_state()) {
self.new_generation(effects)
} else {
self.current_generation
};
let env = Arc::new(ThreadSafeEnvironment::new(parent, generation));
let gen_env = Arc::new(GenerationalEnvironment {
inner: env.clone(),
generation,
parent: None, manager: self.clone(),
});
{
if let Ok(mut registry) = self.environment_registry.write() {
registry.entry(generation)
.or_default()
.push(Arc::downgrade(&gen_env));
}
}
if let Some(record) = self.generation_history.iter_mut().find(|r| r.generation == generation) {
record.env_count += 1;
}
gen_env
}
pub fn create_mutation_environment(
&mut self,
base_env: Arc<GenerationalEnvironment>,
variable: String,
value: Value
) -> Arc<GenerationalEnvironment> {
let new_generation = self.new_generation(vec![Effect::State]);
let new_env = base_env.inner.define_cow(variable, value);
let gen_env = Arc::new(GenerationalEnvironment {
inner: new_env,
generation: new_generation,
parent: Some(base_env),
manager: self.clone(),
});
{
if let Ok(mut registry) = self.environment_registry.write() {
registry.entry(new_generation)
.or_default()
.push(Arc::downgrade(&gen_env));
}
}
gen_env
}
pub fn stats(&self) -> GenerationStats {
let active_gens = self.generation_history.len();
let current_env_count = self.generation_history
.back()
.map(|r| r.env_count)
.unwrap_or(0);
GenerationStats {
total_generations: GENERATION_COUNTER.load(Ordering::SeqCst),
active_generations: active_gens,
current_env_count,
estimated_memory_kb: active_gens * 10, }
}
pub fn cleanup_old_generations(&mut self) {
let cutoff = self.generation_history.len().saturating_sub(self.max_history);
for _ in 0..cutoff {
if let Some(record) = self.generation_history.pop_front() {
self.cleanup_generation(record.generation);
}
}
}
fn cleanup_generation(&self, generation: Generation) {
{
if let Ok(mut registry) = self.environment_registry.write() {
if let Some(weak_refs) = registry.remove(&generation) {
let alive_count = weak_refs.iter().filter(|w| w.strong_count() > 0).count();
if alive_count == 0 {
}
}
}
}
}
pub fn force_gc(&mut self) {
{
if let Ok(mut registry) = self.environment_registry.write() {
registry.retain(|_gen, weak_refs| {
weak_refs.retain(|w| w.strong_count() > 0);
!weak_refs.is_empty()
});
}
}
let live_generations: std::collections::HashSet<Generation> = {
if let Ok(registry) = self.environment_registry.read() {
registry.keys().cloned().collect()
} else {
std::collections::HashSet::new()
}
};
self.generation_history.retain(|record| {
live_generations.contains(&record.generation) ||
record.generation == self.current_generation
});
}
pub fn generation_history(&self) -> &VecDeque<GenerationRecord> {
&self.generation_history
}
pub fn is_generation_active(&self, generation: Generation) -> bool {
if let Ok(registry) = self.environment_registry.read() {
registry.get(&generation)
.map(|weak_refs| weak_refs.iter().any(|w| w.strong_count() > 0))
.unwrap_or(false)
} else {
false
}
}
}
impl GenerationalEnvironment {
pub fn inner(&self) -> &Arc<ThreadSafeEnvironment> {
&self.inner
}
pub fn generation(&self) -> Generation {
self.generation
}
pub fn parent(&self) -> Option<&Arc<GenerationalEnvironment>> {
self.parent.as_ref()
}
pub fn lookup(&self, name: &str) -> Option<Value> {
if let Some(value) = self.inner.lookup(name) {
return Some(value);
}
if let Some(parent) = &self.parent {
parent.lookup(name)
} else {
None
}
}
pub fn define(&self, name: String, value: Value) -> Arc<GenerationalEnvironment> {
let new_inner = self.inner.define_cow(name, value);
Arc::new(GenerationalEnvironment {
inner: new_inner,
generation: self.generation,
parent: self.parent.clone(),
manager: self.manager.clone(),
})
}
pub fn mutate(&self, name: String, value: Value) -> Arc<GenerationalEnvironment> {
let mut manager = self.manager.clone();
manager.create_mutation_environment(
Arc::new(GenerationalEnvironment {
inner: self.inner.clone(),
generation: self.generation,
parent: self.parent.clone(),
manager: self.manager.clone(),
}),
name,
value
)
}
pub fn accessible_variables(&self) -> Vec<String> {
let mut vars = self.inner.variable_names();
if let Some(parent) = &self.parent {
vars.extend(parent.accessible_variables());
}
vars.sort();
vars.dedup();
vars
}
pub fn can_access(&self, name: &str) -> bool {
self.lookup(name).is_some()
}
pub fn generation_chain(&self) -> Vec<Generation> {
let mut chain = vec![self.generation];
if let Some(parent) = &self.parent {
chain.extend(parent.generation_chain());
}
chain
}
}
impl Default for GenerationalConfig {
fn default() -> Self {
Self {
max_history: 100,
auto_cleanup: true,
cleanup_threshold: 50,
track_stats: true,
}
}
}
impl GenerationalConfig {
pub fn memory_optimized() -> Self {
Self {
max_history: 20,
auto_cleanup: true,
cleanup_threshold: 10,
track_stats: false,
}
}
pub fn debug_optimized() -> Self {
Self {
max_history: 1000,
auto_cleanup: false,
cleanup_threshold: 500,
track_stats: true,
}
}
}
impl Default for GenerationalEnvManager {
fn default() -> Self {
Self::new()
}
}
unsafe impl Send for GenerationalEnvManager {}
unsafe impl Sync for GenerationalEnvManager {}
unsafe impl Send for GenerationalEnvironment {}
unsafe impl Sync for GenerationalEnvironment {}
unsafe impl Send for GenerationRecord {}
unsafe impl Sync for GenerationRecord {}
unsafe impl Send for GenerationalConfig {}
unsafe impl Sync for GenerationalConfig {}
unsafe impl Send for GenerationStats {}
unsafe impl Sync for GenerationStats {}
impl Clone for GenerationalEnvironment {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
generation: self.generation,
parent: self.parent.clone(),
manager: self.manager.clone(),
}
}
}
impl fmt::Display for GenerationalEnvironment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GenEnv(gen={}, vars={:?})",
self.generation,
self.inner.variable_names())
}
}
impl fmt::Display for GenerationRecord {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Gen {} (envs={}, effects={:?})",
self.generation,
self.env_count,
self.causing_effects)
}
}
impl fmt::Display for GenerationStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GenStats(total={}, active={}, current_envs={}, mem={}KB)",
self.total_generations,
self.active_generations,
self.current_env_count,
self.estimated_memory_kb)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generation_creation() {
let mut manager = GenerationalEnvManager::new();
assert_eq!(manager.current_generation(), 0);
let gen1 = manager.new_generation(vec![Effect::State]);
assert!(gen1 > 0);
assert_eq!(manager.current_generation(), gen1);
let gen2 = manager.new_generation(vec![Effect::IO]);
assert!(gen2 > gen1);
assert_eq!(manager.current_generation(), gen2);
}
#[test]
fn test_environment_creation() {
let mut manager = GenerationalEnvManager::new();
let env = manager.create_environment(None, vec![Effect::Pure]);
assert_eq!(env.generation(), manager.current_generation());
assert!(env.parent().is_none());
}
#[test]
fn test_mutation_creates_new_generation() {
let mut manager = GenerationalEnvManager::new();
let base_env = manager.create_environment(None, vec![Effect::Pure]);
let base_gen = base_env.generation();
let mutated_env = manager.create_mutation_environment(
base_env,
"x".to_string(),
Value::integer(42)
);
assert!(mutated_env.generation() > base_gen);
assert_eq!(mutated_env.lookup("x"), Some(Value::integer(42)));
}
}