90 lines
2.5 KiB
C
90 lines
2.5 KiB
C
|
|
// 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;
|
||
|
|
}
|