@@ -27,28 +27,217 @@ enum _dispatch_windows_port {
2727DISPATCH_PORT_TIMER_CLOCK_WALL ,
2828DISPATCH_PORT_TIMER_CLOCK_UPTIME ,
2929DISPATCH_PORT_TIMER_CLOCK_MONOTONIC ,
30+ DISPATCH_PORT_FILE_HANDLE ,
3031};
3132
3233#pragma  mark dispatch_unote_t
3334
35+ typedef  struct  dispatch_muxnote_s  {
36+ LIST_ENTRY (dispatch_muxnote_s ) dmn_list ;
37+ dispatch_unote_ident_t  dmn_ident ;
38+ int8_t  dmn_filter ;
39+ enum  _dispatch_muxnote_handle_type  {
40+ DISPATCH_MUXNOTE_HANDLE_TYPE_INVALID ,
41+ DISPATCH_MUXNOTE_HANDLE_TYPE_FILE ,
42+ } dmn_handle_type ;
43+ } * dispatch_muxnote_t ;
44+ 
45+ static  LIST_HEAD (dispatch_muxnote_bucket_s , dispatch_muxnote_s )
46+  _dispatch_sources [DSL_HASH_SIZE ];
47+ 
48+ static  SRWLOCK  _dispatch_file_handles_lock  =  SRWLOCK_INIT ;
49+ static  LIST_HEAD (, dispatch_unote_linkage_s ) _dispatch_file_handles ;
50+ 
51+ DISPATCH_ALWAYS_INLINE 
52+ static  inline  struct  dispatch_muxnote_bucket_s  * 
53+ _dispatch_unote_muxnote_bucket (uint32_t  ident )
54+ {
55+ return  & _dispatch_sources [DSL_HASH (ident )];
56+ }
57+ 
58+ DISPATCH_ALWAYS_INLINE 
59+ static  inline  dispatch_muxnote_t 
60+ _dispatch_unote_muxnote_find (struct  dispatch_muxnote_bucket_s  * dmb ,
61+ dispatch_unote_ident_t  ident , int8_t  filter )
62+ {
63+ dispatch_muxnote_t  dmn ;
64+ if  (filter  ==  EVFILT_WRITE ) filter  =  EVFILT_READ ;
65+ LIST_FOREACH (dmn , dmb , dmn_list ) {
66+ if  (dmn -> dmn_ident  ==  ident  &&  dmn -> dmn_filter  ==  filter ) {
67+ break ;
68+ }
69+ }
70+ return  dmn ;
71+ }
72+ 
73+ static  dispatch_muxnote_t 
74+ _dispatch_muxnote_create (dispatch_unote_t  du )
75+ {
76+ dispatch_muxnote_t  dmn ;
77+ int8_t  filter  =  du ._du -> du_filter ;
78+ HANDLE  handle  =  (HANDLE )du ._du -> du_ident ;
79+ 
80+ dmn  =  _dispatch_calloc (1 , sizeof (* dmn ));
81+ if  (dmn  ==  NULL ) {
82+ DISPATCH_INTERNAL_CRASH (0 , "_dispatch_calloc" );
83+ }
84+ dmn -> dmn_ident  =  (dispatch_unote_ident_t )handle ;
85+ dmn -> dmn_filter  =  filter ;
86+ 
87+ switch  (filter ) {
88+ case  EVFILT_SIGNAL :
89+ WIN_PORT_ERROR ();
90+ 
91+ case  EVFILT_WRITE :
92+ case  EVFILT_READ :
93+ switch  (GetFileType (handle )) {
94+ case  FILE_TYPE_UNKNOWN :
95+ // ensure that an invalid handle was not passed 
96+ (void )dispatch_assume (GetLastError () ==  NO_ERROR );
97+ DISPATCH_INTERNAL_CRASH (0 , "unknown handle type" );
98+ 
99+ case  FILE_TYPE_REMOTE :
100+ DISPATCH_INTERNAL_CRASH (0 , "unused handle type" );
101+ 
102+ case  FILE_TYPE_CHAR :
103+ // The specified file is a character file, typically a 
104+ // LPT device or a console. 
105+ WIN_PORT_ERROR ();
106+ 
107+ case  FILE_TYPE_DISK :
108+ // The specified file is a disk file 
109+ dmn -> dmn_handle_type  = 
110+ DISPATCH_MUXNOTE_HANDLE_TYPE_FILE ;
111+ break ;
112+ 
113+ case  FILE_TYPE_PIPE :
114+ // The specified file is a socket, a named pipe, or an 
115+ // anonymous pipe. 
116+ WIN_PORT_ERROR ();
117+ }
118+ 
119+ break ;
120+ 
121+ default :
122+ DISPATCH_INTERNAL_CRASH (0 , "unexpected filter" );
123+ }
124+ 
125+ 
126+ return  dmn ;
127+ }
128+ 
129+ static  void 
130+ _dispatch_muxnote_dispose (dispatch_muxnote_t  dmn )
131+ {
132+ free (dmn );
133+ }
134+ 
135+ DISPATCH_ALWAYS_INLINE 
136+ static  BOOL 
137+ _dispatch_io_trigger (dispatch_muxnote_t  dmn )
138+ {
139+ BOOL  bSuccess ;
140+ 
141+ switch  (dmn -> dmn_handle_type ) {
142+ case  DISPATCH_MUXNOTE_HANDLE_TYPE_INVALID :
143+ DISPATCH_INTERNAL_CRASH (0 , "invalid handle" );
144+ 
145+ case  DISPATCH_MUXNOTE_HANDLE_TYPE_FILE :
146+ bSuccess  =  PostQueuedCompletionStatus (hPort , 0 ,
147+ (ULONG_PTR )DISPATCH_PORT_FILE_HANDLE , NULL );
148+ if  (bSuccess  ==  FALSE) {
149+ DISPATCH_INTERNAL_CRASH (GetLastError (),
150+ "PostQueuedCompletionStatus" );
151+ }
152+ break ;
153+ }
154+ 
155+ return  bSuccess ;
156+ }
157+ 
34158bool 
35- _dispatch_unote_register_muxed (dispatch_unote_t  du   DISPATCH_UNUSED )
159+ _dispatch_unote_register_muxed (dispatch_unote_t  du )
36160{
37- WIN_PORT_ERROR ();
38- return  false;
161+ struct  dispatch_muxnote_bucket_s  * dmb ;
162+ dispatch_muxnote_t  dmn ;
163+ 
164+ dmb  =  _dispatch_unote_muxnote_bucket (du ._du -> du_ident );
165+ dmn  =  _dispatch_unote_muxnote_find (dmb , du ._du -> du_ident ,
166+ du ._du -> du_filter );
167+ if  (dmn ) {
168+ WIN_PORT_ERROR ();
169+ } else  {
170+ dmn  =  _dispatch_muxnote_create (du );
171+ if  (dmn ) {
172+ if  (_dispatch_io_trigger (dmn ) ==  FALSE) {
173+ _dispatch_muxnote_dispose (dmn );
174+ dmn  =  NULL ;
175+ } else  {
176+ LIST_INSERT_HEAD (dmb , dmn , dmn_list );
177+ }
178+ }
179+ }
180+ 
181+ if  (dmn ) {
182+ dispatch_unote_linkage_t  dul  =  _dispatch_unote_get_linkage (du );
183+ 
184+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
185+ LIST_INSERT_HEAD (& _dispatch_file_handles , dul , du_link );
186+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
187+ 
188+ dul -> du_muxnote  =  dmn ;
189+ _dispatch_unote_state_set (du , DISPATCH_WLH_ANON ,
190+ DU_STATE_ARMED );
191+ }
192+ 
193+ return  dmn  !=  NULL ;
39194}
40195
41196void 
42- _dispatch_unote_resume_muxed (dispatch_unote_t  du   DISPATCH_UNUSED )
197+ _dispatch_unote_resume_muxed (dispatch_unote_t  du )
43198{
44- WIN_PORT_ERROR ();
199+ dispatch_unote_linkage_t  dul  =  _dispatch_unote_get_linkage (du );
200+ dispatch_muxnote_t  dmn  =  dul -> du_muxnote ;
201+ dispatch_assert (_dispatch_unote_registered (du ));
202+ _dispatch_io_trigger (dmn );
45203}
46204
47205bool 
48- _dispatch_unote_unregister_muxed (dispatch_unote_t  du   DISPATCH_UNUSED )
206+ _dispatch_unote_unregister_muxed (dispatch_unote_t  du )
49207{
50- WIN_PORT_ERROR ();
51- return  false;
208+ dispatch_unote_linkage_t  dul  =  _dispatch_unote_get_linkage (du );
209+ dispatch_muxnote_t  dmn  =  dul -> du_muxnote ;
210+ 
211+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
212+ LIST_REMOVE (dul , du_link );
213+ _LIST_TRASH_ENTRY (dul , du_link );
214+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
215+ dul -> du_muxnote  =  NULL ;
216+ 
217+ LIST_REMOVE (dmn , dmn_list );
218+ _dispatch_muxnote_dispose (dmn );
219+ 
220+ _dispatch_unote_state_set (du , DU_STATE_UNREGISTERED );
221+ return  true;
222+ }
223+ 
224+ static  void 
225+ _dispatch_event_merge_file_handle ()
226+ {
227+ dispatch_unote_linkage_t  dul , dul_next ;
228+ 
229+ AcquireSRWLockExclusive (& _dispatch_file_handles_lock );
230+ LIST_FOREACH_SAFE (dul , & _dispatch_file_handles , du_link , dul_next ) {
231+ dispatch_unote_t  du  =  _dispatch_unote_linkage_get_unote (dul );
232+ 
233+ // consumed by dux_merge_evt() 
234+ _dispatch_retain_unote_owner (du );
235+ dispatch_assert (dux_needs_rearm (du ._du ));
236+ _dispatch_unote_state_clear_bit (du , DU_STATE_ARMED );
237+ os_atomic_store2o (du ._dr , ds_pending_data , ~1 , relaxed );
238+ dux_merge_evt (du ._du , EV_ADD  | EV_ENABLE  | EV_DISPATCH , 1 , 0 );
239+ }
240+ ReleaseSRWLockExclusive (& _dispatch_file_handles_lock );
52241}
53242
54243#pragma  mark timers
@@ -221,6 +410,10 @@ _dispatch_event_loop_drain(uint32_t flags)
221410_dispatch_event_merge_timer (DISPATCH_CLOCK_MONOTONIC );
222411break ;
223412
413+ case  DISPATCH_PORT_FILE_HANDLE :
414+ _dispatch_event_merge_file_handle ();
415+ break ;
416+ 
224417default :
225418DISPATCH_INTERNAL_CRASH (ulCompletionKey ,
226419"unsupported completion key" );
0 commit comments