Merge pull request #2310 from lambdageek/dev/bug-36305
[mono.git] / mcs / class / System / System / IOSelector.cs
1 // System/System.IOSelector.cs
2 //
3 // Authors:
4 //      Ludovic Henry <ludovic@xamarin.com>
5 //
6 // Copyright (C) 2015 Xamarin, Inc. (https://www.xamarin.com)
7 //
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System.Runtime.CompilerServices;
30 using System.Runtime.InteropServices;
31 using System.Runtime.Remoting.Messaging;
32 using System.Threading;
33
34 namespace System
35 {
36         internal enum IOOperation : int
37         {
38                 /* Keep in sync with MonoIOOperation in mono/metadata/threadpool-ms-io.c */
39
40                 Read  = 1 << 0,
41                 Write = 1 << 1,
42         }
43
44         internal delegate void IOAsyncCallback (IOAsyncResult ioares);
45
46         [StructLayout (LayoutKind.Sequential)]
47         internal abstract class IOAsyncResult : IAsyncResult
48         {
49                 AsyncCallback async_callback;
50                 object async_state;
51
52                 ManualResetEvent wait_handle;
53                 bool completed_synchronously;
54                 bool completed;
55
56                 protected IOAsyncResult ()
57                 {
58                 }
59
60                 protected void Init (AsyncCallback async_callback, object async_state)
61                 {
62                         this.async_callback = async_callback;
63                         this.async_state = async_state;
64
65                         completed = false;
66                         completed_synchronously = false;
67
68                         if (wait_handle != null)
69                                 wait_handle.Reset ();
70                 }
71
72                 protected IOAsyncResult (AsyncCallback async_callback, object async_state)
73                 {
74                         this.async_callback = async_callback;
75                         this.async_state = async_state;
76                 }
77
78                 public AsyncCallback AsyncCallback
79                 {
80                         get { return async_callback; }
81                 }
82
83                 public object AsyncState
84                 {
85                         get { return async_state; }
86                 }
87
88                 public WaitHandle AsyncWaitHandle
89                 {
90                         get {
91                                 lock (this) {
92                                         if (wait_handle == null)
93                                                 wait_handle = new ManualResetEvent (completed);
94                                         return wait_handle;
95                                 }
96                         }
97                 }
98
99                 public bool CompletedSynchronously
100                 {
101                         get {
102                                 return completed_synchronously;
103                         }
104                         protected set {
105                                 completed_synchronously = value;
106                         }
107                 }
108
109                 public bool IsCompleted
110                 {
111                         get {
112                                 return completed;
113                         }
114                         protected set {
115                                 completed = value;
116                                 lock (this) {
117                                         if (value && wait_handle != null)
118                                                 wait_handle.Set ();
119                                 }
120                         }
121                 }
122
123                 internal abstract void CompleteDisposed();
124         }
125
126         [StructLayout (LayoutKind.Sequential)]
127         internal class IOSelectorJob : IThreadPoolWorkItem
128         {
129                 /* Keep in sync with MonoIOSelectorJob in mono/metadata/threadpool-ms-io.c */
130                 IOOperation operation;
131                 IOAsyncCallback callback;
132                 IOAsyncResult state;
133
134                 public IOSelectorJob (IOOperation operation, IOAsyncCallback callback, IOAsyncResult state)
135                 {
136                         this.operation = operation;
137                         this.callback = callback;
138                         this.state = state;
139                 }
140
141                 void IThreadPoolWorkItem.ExecuteWorkItem ()
142                 {
143                         this.callback (this.state);
144                 }
145
146                 void IThreadPoolWorkItem.MarkAborted (ThreadAbortException tae)
147                 {
148                 }
149
150                 public void MarkDisposed ()
151                 {
152                         state.CompleteDisposed ();
153                 }
154         }
155
156         internal static class IOSelector
157         {
158                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
159                 public static extern void Add (IntPtr handle, IOSelectorJob job);
160
161                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
162                 public static extern void Remove (IntPtr handle);
163         }
164 }