[jcej@chiroptera 010]$./message_queue 4 2 (8910|1024) Task ctor 0xbffff9c4 (8910|2050) Task 0xbffff9c4 starts in thread 2050 (8910|1025) Task 0xbffff9c4 starts in thread 1025 (8910|1024) Block ctor 0x8052398 (8910|1024) Block ctor 0x8052488 (8910|1024) Block ctor 0x8052578 (8910|1024) Block ctor 0x8052668 (8910|1024) Block ctor 0x8052758 (8910|1025) Block 0x8052398 contains (This is message 0.) (8910|2050) Block 0x8052488 contains (This is message 1.) (8910|1025) Block dtor 0x8052398 (8910|1025) Block 0x8052578 contains (This is message 2.) (8910|2050) Block dtor 0x8052488 (8910|2050) Block 0x8052668 contains (This is message 3.) (8910|1025) Block dtor 0x8052578 (8910|1025) Task close 0xbffff9c4 (8910|2050) Block dtor 0x8052668 (8910|2050) Task close 0xbffff9c4 (8910|1024) Task dtor 0xbffff9c4 (8910|1024) Block dtor 0x8052758 (8910|1024) Application exiting [jcej@chiroptera 010]$
Notice that each Block ctor has a corresponding Block dtor. We've proven the point that all memory gets cleaned up. We also see that both threads get to do some work and that both close as expected.
It's also worth mentioning that it's just an accident that all of the blocks are created and enqueued before any are processed. Run the test on a multi-processor or with more iterations and you'll see some get processed before all are created.