[LLVMdev] [PATCH] Circular Buffered Debug Stream
David Greene
dag at cray.com
Fri Dec 18 18:20:25 PST 2009
On Friday 18 December 2009 19:47, Chris Lattner wrote:
> On Dec 18, 2009, at 3:46 PM, David Greene wrote:
> > + /// circular_raw_ostream - A raw_ostream that saves its output in a
> > + /// circular buffer.
>
> A better description would be "which *can* save its data to a circular
> buffer, or can pass it through directly to an underlying stream if
> specified with a buffer of zero."
Make sense.
> When it is buffering, what causes it to flush? Your current model
> requires "printLog" which is not an obvious name for this, would it be
> better to do it on destruction? How about using something like
> flush_to_underlying_stream() or something like that?
Currently, it uses a signal handler. It's important that one gets output
on a SIGTERM, SIGSGEV and other such things and I don't know that object
desctruction is guaranteed in those cases.
Eventually we'll want to dump on SIGUSER1 as well but there's no generic
libSystem hook for that yet.
> > + /// DELETE_STREAM - Tell the destructor to delete the held
> > stream.
> > + ///
> > + static const bool DELETE_STREAM = true;
> > +
> > + /// PRESERVE_STREAM - Tell the destructor to not delete the held
> > + /// stream.
> > + ///
> > + static const bool PRESERVE_STREAM = false;
>
> I don't find these to be very clear names. How about giving them a
> name involving 'ownership' like TAKES_OWNERSHIP? "preservation" isn't
> really the same as "not deleting when the stream is destroyed" to me.
That's a good idea.
I just took these from what Dan (I think) did in formatted_raw_ostream.
I'll change them here and rename DeleteStream to OwnsStream as well.
> > + /// TheStream - The real stream we output to. We set it to be
> > + /// unbuffered, since we're already doing our own buffering.
> > + ///
> > + raw_ostream *TheStream;
>
> Now that I understand the model :) I don't see why you need to fiddle
> with the underlying buffering of TheStream. In the dbgs() use case,
> the underlying stream will be errs() which is already unbuffered.
Might circular_raw_ostream be used with other streams at some point?
> > + /// printLog - Dump the contents of the buffer to Stream.
> > + ///
> > + void printLog(void) {
> > + TheStream->write(BufferArray, BufferSize);
> > + Cur = BufferArray;
> > + }
>
> If the buffer has circled around, won't this print it out-of-order?
> If the current pointer is 5 and the length is 10, it seems like this
> should do a write([5..9]) then write([0..4])?
Aha! Good catch. This worked differently in our implementation here. I'll
fix it.
> > + /// current_pos - Return the current position within the stream,
> > + /// not counting the bytes currently in the buffer.
> > + virtual uint64_t current_pos() {
>
> This is now const on mainline.
Ok.
> > + public:
> > + /// circular_raw_ostream - Open the specified file for
> > + /// writing.
>
> This is not a file, please read the comments you're copying :)
:)
> > + ///
> > + /// As a side effect, if BuffSize is nonzero, the given Stream is
> > + /// set to be Unbuffered. This is because circular_raw_ostream
> > + /// does its own buffering, so it doesn't want another layer of
> > + /// buffering to be happening underneath it.
> > + ///
>
> Again, I don't think this should happen anymore. You should add some
> comment about what Delete does, and change it to not use 'false' as I
> asked for before.
I've cleaned this up, but see my question about usage with other streams.
> > + circular_raw_ostream(raw_ostream &Stream, size_t BuffSize = 8192,
> > + bool Delete = false)
> > + : raw_ostream(/*unbuffered*/true),
> > + TheStream(0),
> > + DeleteStream(PRESERVE_STREAM),
> > + BufferSize(BuffSize),
> > + BufferArray(0) {
> > + if (BufferSize > 0)
>
> Please change all these predicates to BufferSize != 0 instead of using
Any particular reason? I'll do it but I'm just curious. It seems that if
these things get changed to signed someday it could cause trouble.
> > +#include "llvm/Support/circular_raw_ostream.h"
> > +
> > +#include <algorithm>
> > +
> > +using namespace llvm;
> > +
> > +void circular_raw_ostream::write_impl(const char *Ptr, size_t Size) {
> > + if (BufferSize > 0) {
>
> Please use:
>
> if (BufferSize == 0) {
> .. write ..
> return;
> }
>
> to reduce nesting.
Ok.
> > +void circular_raw_ostream::dumpLog(void) {
> > + if (BufferSize > 0) {
> > + // Write out the buffer
> > + const char *msg = "*** Log Output ***\n";
> > + int num = std::strlen(msg);
> > +
> > + TheStream->write(msg, num);
> > + printLog();
> > + }
> > +}
>
> I'm still unclear about this and printLog. The "Log Output" prefix is
> confusing to me, because this isn't a log file. Maybe just remove the
> prefix?
I wanted something to signify in the output where the debug dump starts.
That's for that case where some stuff might still get output through errs().
I anticipate that while I'll change most uses of errs() to dbgs(), we
probably don't want to change all of them.
I agree the naming here is poor. I'll fix that.
-Dave
More information about the llvm-dev
mailing list