EDM FAQ: The Streamer() method


The Streamer method is supposed to "serialize" and "deserialize" an object into ROOT's TBuffer structure in order to write and read an object to disk, respectively. In some cases, folks have implemented Streamer() by delegating the read and write functionality to separate methods such as readFromBuffer() and writeToBuffer(). This is fine, so long as the Streamer() method, as defined by the ROOT Object I/O system, is made available. See the EdmObjects classes for examples of writing streamers for a variety of data types.

Classes do not declare the Streamer() method themselves. Streamer() is defined by ROOT's ClassDef() macro with the following signature:

public: virtual void Streamer(TBuffer& iobuffer) ;

The Streamer method handles both reading and writing of objects, depending on the state of the iobuffer argument. The implementation of a Streamer contains one block of code for reading, one piece for writing, and one piece to handle an unknown iobuffer state. Within the read block, one must check the class version that was written out in order to determine how to read the object back in. Within both read and write blocks, one must set or check byte counts to be sure that the correct number of bytes is actually read/written to the I/o stream by each object. Finally, within each read and write block, one first streamers the immediate base class component of one's class, then one streamers the individual data members of one's class. These can be streamered either by using redirection operators >> and << associated with the TBuffer class or by using a Streamer method of the appropriate class. As an example, here is a editted version of the ToyMuon::Streamer(). Note that many methods are specifically qualified by their class name since they may be called through a base class pointer.

void ToyMuon::Streamer(TBuffer& iobuffer)
{ unsigned int start = 0 ;  unsigned int byte_count = 0 ;// init local variables

  if (iobuffer.IsReading()) // READ BLOCK
    { // Read the class version at time of writing of object, set up byte count
      Version_t original_version = iobuffer.ReadVersion(&start, &byte_count) ;
      if (original_version == 1) // Treat version 1 of this class's streamer
        { StorableObject::Streamer(iobuffer) ; // Read base class
          iobuffer >> _em_charge ;             // Read a byte code for +-1/0
          iobuffer >> _is_golden ;             // Read a bool
          _p_track.Streamer(iobuffer) ;        // Read a link to a track
        }
      else                       // Unknown version... cannot read it in
        { std::cerr << "ToyMuon::Streamer(IsReading): "
                       "Unsupported ToyMuon class version cannot be treated.\n" ;
        }
      // Now perform the byte count check
      iobuffer.CheckByteCount(start, byte_count, ToyMuon::IsA()) ;
    }
  else if (iobuffer.IsWriting()) // WRITE BLOCK
    { // Write the current class version and save space for a byte count
      byte_count = iobuffer.WriteVersion(ToyMuon::IsA(), kTRUE) ;
      // Get current class version to allow fall-back to old versions in future
      Version_t current_version = ToyMuon::class_version() ;
      // Now the read/write version blocks look the same
      if (current_version == 1)
        { StorableObject::Streamer(iobuffer) ; // Write the base class piece
          iobuffer << _em_charge ;             // Write a byte switch +-1/0
          iobuffer << _is_golden ;             // Write a bool
          _p_track.Streamer(iobuffer) ;        // Write a link to a track
        }
      else                       // Unknown version... cannot write it out
        { std::cerr << "ToyMuon::Streamer(IsWriting): "
                       "Unsupported ToyMuon class version cannot be treated.\n" ;
        }
      // Now go back and write out the number of bytes just streamed out
      iobuffer.SetByteCount(byte_count, kTRUE) ;
    }
  else // UNKNOWN ACTION BLOCK
    { std::cerr << "ToyMuon::Streamer(): NOTHING DONE.\n" ;
    }
If the data type you intend to stream out is not supported by TBuffer and does not have its own Streamer(), consider using on the of the TBuffer I/O extensions defined in the EdmUtilities package.


Comments on this page may be sent to Rob Kennedy