I am building a system for multi-agents simulations. I have an Agent trait, and many types that implement it. Then there's a Kernel type -- the kernel handles some startup operations and then acts as a router of messages between the agents.
The problem is that the agents need to have a reference to the kernel (to send messages), and the kernel needs to have a reference to the agents (to send messages and perform some other operations). This cyclic reference logic is not accepted by the borrow checker, so I tried to sidestep it with a RefCell, but I ran into problems with that too.
Here's a sketch of the types:
pub struct Kernel {
// other irrelevant fields have been omitted
pub agents: HashMap<AgentID, Box<dyn Agent>>,
}
impl Kernel {
pub fn send(&mut self, ...) {
// ..
}
}
pub struct CustomAgent {
id: AgentID,
kernel_ref: Rc<RefCell<Kernel>>,
}
impl Agent for CustomAgent {
// ...
}
The problem comes in in the initialization stage: I create the Kernel first, then the Kernel needs to create the agents and pass a reference to itself to each agent. I cannot find a way to make it work. Each agent needs a mutable reference to the kernel because sending messages mutates the state of the kernel. That's why I had to resort to a RefCell. I cannot find a way to construct the Agent types and passing them a reference to the kernel.