// retoor <retoor@molodetz.nl>
#include "spawn_tracker.h"
#include "r_config.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct spawn_tracker_t {
int current_depth;
int total_spawns;
int max_depth;
int max_total;
pthread_mutex_t lock;
};
static struct spawn_tracker_t *instance = NULL;
spawn_tracker_handle spawn_tracker_get_instance(void) {
if (instance) return instance;
instance = calloc(1, sizeof(struct spawn_tracker_t));
if (!instance) return NULL;
r_config_handle cfg = r_config_get_instance();
instance->max_depth = r_config_get_max_spawn_depth(cfg);
instance->max_total = r_config_get_max_total_spawns(cfg);
instance->current_depth = 0;
instance->total_spawns = 0;
pthread_mutex_init(&instance->lock, NULL);
return instance;
}
void spawn_tracker_destroy(void) {
if (!instance) return;
pthread_mutex_destroy(&instance->lock);
free(instance);
instance = NULL;
}
bool spawn_tracker_can_spawn(spawn_tracker_handle tracker) {
if (!tracker) return false;
pthread_mutex_lock(&tracker->lock);
bool allowed = (tracker->current_depth < tracker->max_depth) &&
(tracker->total_spawns < tracker->max_total);
pthread_mutex_unlock(&tracker->lock);
return allowed;
}
int spawn_tracker_begin(spawn_tracker_handle tracker) {
if (!tracker) return -1;
pthread_mutex_lock(&tracker->lock);
tracker->current_depth++;
tracker->total_spawns++;
int depth_token = tracker->current_depth;
fprintf(stderr, "[SpawnTracker] depth=%d/%d total=%d/%d\n",
tracker->current_depth, tracker->max_depth,
tracker->total_spawns, tracker->max_total);
pthread_mutex_unlock(&tracker->lock);
return depth_token;
}
void spawn_tracker_end(spawn_tracker_handle tracker, int depth_token) {
if (!tracker) return;
(void)depth_token;
pthread_mutex_lock(&tracker->lock);
if (tracker->current_depth > 0) {
tracker->current_depth--;
}
fprintf(stderr, "[SpawnTracker] agent finished, depth=%d/%d total=%d/%d\n",
tracker->current_depth, tracker->max_depth,
tracker->total_spawns, tracker->max_total);
pthread_mutex_unlock(&tracker->lock);
}
bool spawn_tracker_validate_result(const char *result) {
if (!result) return false;
size_t len = strlen(result);
if (len < SPAWN_RESULT_MIN_LENGTH) return false;
if (strstr(result, "Error:") == result) return false;
return true;
}