3

I am trying to implement a server using Mio and a reactor pattern. I want my Reactor to handle both TcpListeners and TcpStreams, so abstracting over that is my real challenge here.

I have a trait ReAgent that implements various handlers for informing the Reactor about changes in status, while Reactor informs each individual ReAgent about events important to that ReAgent. In turn, I'll have two different ReAgent types, one for accepting (TcpListeners) which will spawn clients (TcpStreams) to pass back to the Reactor for event handling. A very standard Reactor pattern for multiple server endpoints; I've written half a dozen of these in C/C++ over my career. Eliding details about my TokenPool, etc., here's where my headache lies:

pub struct Reactor<'a> {
    poll: Poll,
    agents: HashMap<Token, Box<ReAgent + 'a>>,
    tokens: TokenPool,
}


impl<'a> Reactor<'a> {
    pub fn add_agent<R: ReAgent + 'a>(&mut self, mut agent: Box<R>) -> Result<()>
    {
        if let Some(next_token) = self.tokens.pop() {
            agent.set_token(next_token);
            self.agents.insert(agent.get_token(), agent);
            return Ok(())
        } 
        bail!(ErrorKind::ConnectionsExhausted)
    }
}

//... 

/// Received a Box<ReAgent> (a Client);
/// add and start conversation
Some(boxed_agent) => self.add_agent(boxed_agent)

When I compile this, I get:

Some(boxed_agent) => self.add_agent(boxed_agent)
                          ^^^^^^^^^ `reagent::ReAgent` does not have a constant size known at compile-time

... which I don't get at all. It's a Box. A Box has a known constant size at compile time. That's the whole point here of using Box to support a dynamic type object, right? The client has a known size, it's a concrete implementation of ReAgent.

What am I missing?

I know I'll probably have to use a RefCell later, since I'm mutating the ReAgent to set its polling token; that's for later, I just want to get past this.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Elf Sternberg
  • 16,129
  • 6
  • 60
  • 68
  • 1
    "C/C++", C or C++ ? XD that make me mad... whatever your MCVE is not complete what is `reagent::ReAgent` ? (I suppose it's a trait and this trait don't have a compile size, AFAIK) – Stargateur Jan 19 '18 at 00:37
  • 1
    I think [What does "Sized is not implemented" mean?](https://stackoverflow.com/questions/28044231/what-does-sized-is-not-implemented-mean) might be a closer match. – trent Jan 19 '18 at 02:16
  • 1
    Either way, the application is: add `+ ?Sized` to the bounds on `R` and it should work :) – trent Jan 19 '18 at 02:18
  • 1
    Addressing your title: `Box` is sized, as you said. That's why the error message says: ***\`reagent::ReAgent\`** does not have a constant size known at compile-time*. – Shepmaster Jan 19 '18 at 03:00
  • 1
    @Shepmaster That's my point: Box is a pointer object. It has a constant size. Why does the receiver function care what size the thing pointed to? None of the recommended answers pointed to give me a clear answer to that question. – Elf Sternberg Jan 19 '18 at 19:46
  • @ElfSternberg the first sentence of the [accepted answer of the first linked duplicate](https://stackoverflow.com/a/28045264/155423) states, emphasis mine: *The `Sized` trait is rather special, so special that **it is a default bound on type parameters** in most situations*. You have a type parameter (`R`). It has the `Sized` type bound. The trait type `ReAgent` does not have a size, thus it fails the requirements. – Shepmaster Jan 19 '18 at 20:06

0 Answers0