Repository: actix/actix (language: rust)

Issue:
No way to flush FramedWrite streams?
I have an actor which reads from TCP using `add_stream` and `StreamHandler`. It also owns a `FramedWrite<WriteHalf<TcpStream>, SomeCodec>`, which it often writes to inside of the `StreamHandler`. Stopping the actor can leave unsent messages in that write stream -- I can understand that simply stopping the actor, it wouldn't necessarily know how to flush the stream. Hence, seems like there should be a flush method available on `FramedWrite`.

I think this relates heavily to #132 which would also help a lot.

EDIT: I'd also expect `.close()` on the framed write to flush, but it doesn't appear to.


Discussion / hints:
@fafhrd91 Should we add option for manual flush? Or should it maybe called in destructor?
manual flush seems like it could handle more diverse cases than only flushing in the destructor. I think both would be good to have in this case? 
I'd go for both personally. I'm happy to look into making a PR tomorrow if you're open to a contribution here.
@DoumanAsh i think it is fine
@Sushisource if you're going to work on it, please note that we now have `0.8` on master and separate branch on `0.7`


@DoumanAsh Sounds good - I'm fine with it going into either personally, if 0.8 is gonna be released relatively soon. I'm happy to do it wherever is easiest 

Fix patch:
diff --git a/src/io.rs b/src/io.rs
index ebf156ff8..a256723c0 100644
--- a/src/io.rs
+++ b/src/io.rs
@@ -292,7 +292,8 @@ where
     }
 }
 
-/// A wrapper for the `AsyncWrite` and `Encoder` types.
+/// A wrapper for the `AsyncWrite` and `Encoder` types. The AsyncWrite will be flushed when this
+/// struct is dropped.
 pub struct FramedWrite<T: AsyncWrite, U: Encoder> {
     enc: U,
     inner: UnsafeWriter<T, U::Error>,
@@ -392,3 +393,16 @@ impl<T: AsyncWrite, U: Encoder> FramedWrite<T, U> {
         self.inner.0.borrow().handle
     }
 }
+
+impl<T: AsyncWrite, U: Encoder> Drop for FramedWrite<T, U> {
+    fn drop(&mut self) {
+        // Attempts to write any remaining bytes to the stream and flush it
+        let mut async_writer = self.inner.1.borrow_mut();
+        let inner = self.inner.0.borrow_mut();
+        if !inner.buffer.is_empty() {
+            // Results must be ignored during drop, as the errors cannot be handled meaningfully
+            let _ = async_writer.write(&inner.buffer);
+            let _ = async_writer.flush();
+        }
+    }
+}


Test patch: