Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

win: guarantee write callback ordering

  • Loading branch information...
commit f0044c007a24ea4dd18f979c59b16c5f1b02fa8f 1 parent 2640aae
Pieter Noordhuis authored September 16, 2011 piscisaureus committed September 16, 2011
1  AUTHORS
@@ -21,3 +21,4 @@ Clifford Heath <clifford.heath@gmail.com>
21 21
 Jorge Chamorro Bieling <jorge@jorgechamorro.com>
22 22
 Luis Lavena <luislavena@gmail.com>
23 23
 Matthew Sporleder <msporleder@gmail.com>
  24
+Pieter Noordhuis <pcnoordhuis@gmail.com>
4  include/uv-private/uv-win.h
@@ -99,7 +99,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
99 99
   struct uv_req_s* next_req;
100 100
 
101 101
 #define UV_WRITE_PRIVATE_FIELDS           \
102  
-  /* empty */
  102
+  int done;                               \
  103
+  uv_write_t* next_write;
103 104
 
104 105
 #define UV_CONNECT_PRIVATE_FIELDS         \
105 106
   /* empty */
@@ -125,6 +126,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
125 126
 
126 127
 #define uv_stream_connection_fields       \
127 128
   unsigned int write_reqs_pending;        \
  129
+  uv_write_t* write_reqs_tail;            \
128 130
   uv_shutdown_t* shutdown_req;
129 131
 
130 132
 #define uv_stream_server_fields           \
1  src/win/internal.h
@@ -110,6 +110,7 @@ void uv_process_reqs(uv_loop_t* loop);
110 110
  */
111 111
 void uv_stream_init(uv_loop_t* loop, uv_stream_t* handle);
112 112
 void uv_connection_init(uv_stream_t* handle);
  113
+void uv_insert_pending_write_req(uv_stream_t* handle, uv_write_t* req);
113 114
 
114 115
 size_t uv_count_bufs(uv_buf_t bufs[], int count);
115 116
 
43  src/win/pipe.c
@@ -747,8 +747,11 @@ int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle,
747 747
   req->type = UV_WRITE;
748 748
   req->handle = (uv_stream_t*) handle;
749 749
   req->cb = cb;
  750
+  req->done = 0;
750 751
   memset(&req->overlapped, 0, sizeof(req->overlapped));
751 752
 
  753
+  uv_insert_pending_write_req((uv_stream_t*)handle, req);
  754
+
752 755
   result = WriteFile(handle->handle,
753 756
                      bufs[0].base,
754 757
                      bufs[0].len,
@@ -886,22 +889,38 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle,
886 889
 
887 890
   handle->write_queue_size -= req->queued_bytes;
888 891
 
889  
-  if (req->cb) {
890  
-    if (!REQ_SUCCESS(req)) {
891  
-      loop->last_error = GET_REQ_UV_ERROR(req);
892  
-      ((uv_write_cb)req->cb)(req, -1);
  892
+  req->done = 1;
  893
+
  894
+  while (handle->write_reqs_tail) {
  895
+    req = handle->write_reqs_tail->next_write;
  896
+
  897
+    if (!req->done) {
  898
+      break;
  899
+    }
  900
+
  901
+    if (req == handle->write_reqs_tail) {
  902
+      handle->write_reqs_tail = NULL;
893 903
     } else {
894  
-      ((uv_write_cb)req->cb)(req, 0);
  904
+      handle->write_reqs_tail->next_write = req->next_write;
895 905
     }
896  
-  }
897 906
 
898  
-  handle->write_reqs_pending--;
899  
-  if (handle->write_reqs_pending == 0 &&
900  
-      handle->flags & UV_HANDLE_SHUTTING) {
901  
-    uv_want_endgame(loop, (uv_handle_t*)handle);
902  
-  }
  907
+    if (req->cb) {
  908
+      if (!REQ_SUCCESS(req)) {
  909
+        loop->last_error = GET_REQ_UV_ERROR(req);
  910
+        ((uv_write_cb)req->cb)(req, -1);
  911
+      } else {
  912
+        ((uv_write_cb)req->cb)(req, 0);
  913
+      }
  914
+    }
903 915
 
904  
-  DECREASE_PENDING_REQ_COUNT(handle);
  916
+    handle->write_reqs_pending--;
  917
+    if (handle->flags & UV_HANDLE_SHUTTING &&
  918
+        handle->write_reqs_pending == 0) {
  919
+      uv_want_endgame(loop, (uv_handle_t*)handle);
  920
+    }
  921
+
  922
+    DECREASE_PENDING_REQ_COUNT(handle);
  923
+  }
905 924
 }
906 925
 
907 926
 
14  src/win/stream.c
@@ -41,6 +41,7 @@ void uv_stream_init(uv_loop_t* loop, uv_stream_t* handle) {
41 41
 void uv_connection_init(uv_stream_t* handle) {
42 42
   handle->flags |= UV_HANDLE_CONNECTION;
43 43
   handle->write_reqs_pending = 0;
  44
+  handle->write_reqs_tail = NULL;
44 45
 
45 46
   uv_req_init(handle->loop, (uv_req_t*) &(handle->read_req));
46 47
   handle->read_req.type = UV_READ;
@@ -48,6 +49,19 @@ void uv_connection_init(uv_stream_t* handle) {
48 49
 }
49 50
 
50 51
 
  52
+void uv_insert_pending_write_req(uv_stream_t* handle, uv_write_t* req) {
  53
+  req->next_write = NULL;
  54
+  if (handle->write_reqs_tail) {
  55
+    req->next_write = handle->write_reqs_tail->next_write;
  56
+    handle->write_reqs_tail->next_write = req;
  57
+    handle->write_reqs_tail = req;
  58
+  } else {
  59
+    req->next_write = req;
  60
+    handle->write_reqs_tail = req;
  61
+  }
  62
+}
  63
+
  64
+
51 65
 int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb) {
52 66
   switch (stream->type) {
53 67
     case UV_TCP:
39  src/win/tcp.c
@@ -644,8 +644,11 @@ int uv_tcp_write(uv_loop_t* loop, uv_write_t* req, uv_tcp_t* handle,
644 644
   req->type = UV_WRITE;
645 645
   req->handle = (uv_stream_t*) handle;
646 646
   req->cb = cb;
  647
+  req->done = 0;
647 648
   memset(&req->overlapped, 0, sizeof(req->overlapped));
648 649
 
  650
+  uv_insert_pending_write_req((uv_stream_t*)handle, req);
  651
+
649 652
   result = WSASend(handle->socket,
650 653
                    (WSABUF*)bufs,
651 654
                    bufcnt,
@@ -781,18 +784,34 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
781 784
 
782 785
   handle->write_queue_size -= req->queued_bytes;
783 786
 
784  
-  if (req->cb) {
785  
-    loop->last_error = GET_REQ_UV_SOCK_ERROR(req);
786  
-    ((uv_write_cb)req->cb)(req, loop->last_error.code == UV_OK ? 0 : -1);
787  
-  }
  787
+  req->done = 1;
788 788
 
789  
-  handle->write_reqs_pending--;
790  
-  if (handle->flags & UV_HANDLE_SHUTTING &&
791  
-      handle->write_reqs_pending == 0) {
792  
-    uv_want_endgame(loop, (uv_handle_t*)handle);
793  
-  }
  789
+  while (handle->write_reqs_tail) {
  790
+    req = handle->write_reqs_tail->next_write;
794 791
 
795  
-  DECREASE_PENDING_REQ_COUNT(handle);
  792
+    if (!req->done) {
  793
+      break;
  794
+    }
  795
+
  796
+    if (req == handle->write_reqs_tail) {
  797
+      handle->write_reqs_tail = NULL;
  798
+    } else {
  799
+      handle->write_reqs_tail->next_write = req->next_write;
  800
+    }
  801
+
  802
+    if (req->cb) {
  803
+      loop->last_error = GET_REQ_UV_SOCK_ERROR(req);
  804
+      ((uv_write_cb)req->cb)(req, loop->last_error.code == UV_OK ? 0 : -1);
  805
+    }
  806
+
  807
+    handle->write_reqs_pending--;
  808
+    if (handle->flags & UV_HANDLE_SHUTTING &&
  809
+        handle->write_reqs_pending == 0) {
  810
+      uv_want_endgame(loop, (uv_handle_t*)handle);
  811
+    }
  812
+
  813
+    DECREASE_PENDING_REQ_COUNT(handle);
  814
+  }
796 815
 }
797 816
 
798 817
 

0 notes on commit f0044c0

Please sign in to comment.
Something went wrong with that request. Please try again.