mbeckerle commented on a change in pull request #12: Revised daffodil-io module 
to require passing in a FormatInfo object.
URL: https://github.com/apache/incubator-daffodil/pull/12#discussion_r158168354
 
 

 ##########
 File path: 
daffodil-runtime1/src/main/scala/edu/illinois/ncsa/daffodil/processors/Suspension.scala
 ##########
 @@ -98,12 +111,104 @@ trait Suspension
     }
   }
 
+  /**
+   * Run the first time.
+   *
+   */
   final def run(ustate: UState) {
     doTask(ustate)
     if (!isDone) {
-      val mkl = maybeKnownLengthInBits(ustate)
-      setup(ustate, mkl)
+      prepareToSuspend(ustate)
+    }
+  }
+
+  private def prepareToSuspend(ustate: UState) {
+    val mkl = maybeKnownLengthInBits(ustate)
+    //
+    // It seems like we have too many splits going on.
+    //
+    // As written, we have a bunch of suspensions that occur, but have
+    // specifically known length of zero bits. So nothing being written out.
+    // In that case, why do we need to split at all?
+    //
+    val original = 
ustate.dataOutputStream.asInstanceOf[DirectOrBufferedDataOutputStream]
+    if (mkl.isEmpty || (mkl.isDefined && mkl.get > 0)) {
+      //
+      // only split if the length is either unknown
+      // or known and greater than 0.
+      //
+      // If length known 0, then no need for another DOS
+      //
+      splitDOS(ustate, mkl, original)
+    }
+    suspend(ustate, original)
+  }
+
+  private def splitDOS(ustate: UState,
+    maybeKnownLengthInBits: MaybeULong,
+    original: DirectOrBufferedDataOutputStream) {
+    Assert.usage(ustate.currentInfosetNodeMaybe.isDefined)
+
+    val buffered = original.addBuffered
+    buffered.setPriorBitOrder(ustate.bitOrder)
+
+    if (maybeKnownLengthInBits.isDefined) {
+      // since we know the length of the unparsed representation that we're 
skipping for now,
+      // that means we know the absolute position of the bits in the buffer 
we're creating
+      // and that means alignment operations don't have to suspend waiting for 
this knowledge
+      if (original.maybeAbsBitPos0b.isDefined) {
+        // direct streams always know this, but buffered streams may not.
+
+        val originalAbsBitPos0b = original.maybeAbsBitPos0b.getULong
+
+        // we are passed this length (in bits)
+        // and can use it to initialize the absolute bit pos of the buffered 
output stream.
+        //
+        // This allows us to deal with alignment regions, that is, we can 
determine
+        // their size since we know the absolute bit position.
+
+        val mkl = maybeKnownLengthInBits.getULong
+        buffered.setAbsStartingBitPos0b(originalAbsBitPos0b + mkl)
+
+      }
+    } else {
+      log(LogLevel.Debug, "Buffered DOS created for %s without knowning 
absolute start bit pos: %s\n",
+        ustate.currentInfosetNode.erd.diagnosticDebugName, buffered)
+    }
+
+    // the main-thread will carry on using the original ustate but unparsing
+    // into this buffered stream.
+    ustate.dataOutputStream = buffered
+  }
+
+  private def suspend(ustate: UState, original: 
DirectOrBufferedDataOutputStream) {
+    //
+    // clone the ustate for use when evaluating the expression
+    //
+    // TODO: Performance - copying this whole state, just for OVC is painful.
+    // Some sort of copy-on-write scheme would be better.
+    //
+    val didSplit = (ustate.dataOutputStream ne original)
+    val cloneUState = 
ustate.asInstanceOf[UStateMain].cloneForSuspension(original)
+    if (isReadOnly && didSplit) {
+      Assert.invariantFailed("Shouldn't have split. read-only case")
+      //      try {
 
 Review comment:
   Remove commented code. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to