| OLD | NEW | 
|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 5 #ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 
| 6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 6 #define BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 
| 7 | 7 | 
| 8 #include <windows.h> | 8 #include <windows.h> | 
| 9 | 9 | 
| 10 #include <list> | 10 #include <list> | 
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 141 }; | 141 }; | 
| 142 | 142 | 
| 143 //----------------------------------------------------------------------------- | 143 //----------------------------------------------------------------------------- | 
| 144 // MessagePumpForIO extends MessagePumpWin with methods that are particular to a | 144 // MessagePumpForIO extends MessagePumpWin with methods that are particular to a | 
| 145 // MessageLoop instantiated with TYPE_IO. This version of MessagePump does not | 145 // MessageLoop instantiated with TYPE_IO. This version of MessagePump does not | 
| 146 // deal with Windows mesagges, and instead has a Run loop based on Completion | 146 // deal with Windows mesagges, and instead has a Run loop based on Completion | 
| 147 // Ports so it is better suited for IO operations. | 147 // Ports so it is better suited for IO operations. | 
| 148 // | 148 // | 
| 149 class BASE_EXPORT MessagePumpForIO : public MessagePumpWin { | 149 class BASE_EXPORT MessagePumpForIO : public MessagePumpWin { | 
| 150  public: | 150  public: | 
| 151   struct IOContext; | 151   struct BASE_EXPORT IOContext { | 
|  | 152     IOContext(); | 
|  | 153     OVERLAPPED overlapped; | 
|  | 154   }; | 
| 152 | 155 | 
| 153   // Clients interested in receiving OS notifications when asynchronous IO | 156   // Clients interested in receiving OS notifications when asynchronous IO | 
| 154   // operations complete should implement this interface and register themselves | 157   // operations complete should implement this interface and register themselves | 
| 155   // with the message pump. | 158   // with the message pump. | 
| 156   // | 159   // | 
| 157   // Typical use #1: | 160   // Typical use #1: | 
| 158   //   // Use only when there are no user's buffers involved on the actual IO, |  | 
| 159   //   // so that all the cleanup can be done by the message pump. |  | 
| 160   //   class MyFile : public IOHandler { | 161   //   class MyFile : public IOHandler { | 
| 161   //     MyFile() { | 162   //     MyFile() { | 
| 162   //       ... | 163   //       ... | 
| 163   //       context_ = new IOContext; |  | 
| 164   //       context_->handler = this; |  | 
| 165   //       message_pump->RegisterIOHandler(file_, this); |  | 
| 166   //     } |  | 
| 167   //     ~MyFile() { |  | 
| 168   //       if (pending_) { |  | 
| 169   //         // By setting the handler to NULL, we're asking for this context |  | 
| 170   //         // to be deleted when received, without calling back to us. |  | 
| 171   //         context_->handler = NULL; |  | 
| 172   //       } else { |  | 
| 173   //         delete context_; |  | 
| 174   //      } |  | 
| 175   //     } |  | 
| 176   //     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, |  | 
| 177   //                                DWORD error) { |  | 
| 178   //         pending_ = false; |  | 
| 179   //     } |  | 
| 180   //     void DoSomeIo() { |  | 
| 181   //       ... |  | 
| 182   //       // The only buffer required for this operation is the overlapped |  | 
| 183   //       // structure. |  | 
| 184   //       ConnectNamedPipe(file_, &context_->overlapped); |  | 
| 185   //       pending_ = true; |  | 
| 186   //     } |  | 
| 187   //     bool pending_; |  | 
| 188   //     IOContext* context_; |  | 
| 189   //     HANDLE file_; |  | 
| 190   //   }; |  | 
| 191   // |  | 
| 192   // Typical use #2: |  | 
| 193   //   class MyFile : public IOHandler { |  | 
| 194   //     MyFile() { |  | 
| 195   //       ... |  | 
| 196   //       message_pump->RegisterIOHandler(file_, this); | 164   //       message_pump->RegisterIOHandler(file_, this); | 
| 197   //     } | 165   //     } | 
| 198   //     // Plus some code to make sure that this destructor is not called | 166   //     // Plus some code to make sure that this destructor is not called | 
| 199   //     // while there are pending IO operations. | 167   //     // while there are pending IO operations. | 
| 200   //     ~MyFile() { | 168   //     ~MyFile() { | 
| 201   //     } | 169   //     } | 
| 202   //     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, | 170   //     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, | 
| 203   //                                DWORD error) { | 171   //                                DWORD error) { | 
| 204   //       ... | 172   //       ... | 
| 205   //       delete context; | 173   //       delete context; | 
| 206   //     } | 174   //     } | 
| 207   //     void DoSomeIo() { | 175   //     void DoSomeIo() { | 
| 208   //       ... | 176   //       ... | 
| 209   //       IOContext* context = new IOContext; | 177   //       IOContext* context = new IOContext; | 
| 210   //       // This is not used for anything. It just prevents the context from | 178   //       ReadFile(file_, buffer, num_bytes, &read, &context); | 
| 211   //       // being considered "abandoned". |  | 
| 212   //       context->handler = this; |  | 
| 213   //       ReadFile(file_, buffer, num_bytes, &read, &context->overlapped); |  | 
| 214   //     } | 179   //     } | 
| 215   //     HANDLE file_; | 180   //     HANDLE file_; | 
| 216   //   }; | 181   //   }; | 
| 217   // | 182   // | 
| 218   // Typical use #3: | 183   // Typical use #2: | 
| 219   // Same as the previous example, except that in order to deal with the | 184   // Same as the previous example, except that in order to deal with the | 
| 220   // requirement stated for the destructor, the class calls WaitForIOCompletion | 185   // requirement stated for the destructor, the class calls WaitForIOCompletion | 
| 221   // from the destructor to block until all IO finishes. | 186   // from the destructor to block until all IO finishes. | 
| 222   //     ~MyFile() { | 187   //     ~MyFile() { | 
| 223   //       while(pending_) | 188   //       while(pending_) | 
| 224   //         message_pump->WaitForIOCompletion(INFINITE, this); | 189   //         message_pump->WaitForIOCompletion(INFINITE, this); | 
| 225   //     } | 190   //     } | 
| 226   // | 191   // | 
| 227   class IOHandler { | 192   class IOHandler { | 
| 228    public: | 193    public: | 
| 229     virtual ~IOHandler() {} | 194     virtual ~IOHandler() {} | 
| 230     // This will be called once the pending IO operation associated with | 195     // This will be called once the pending IO operation associated with | 
| 231     // |context| completes. |error| is the Win32 error code of the IO operation | 196     // |context| completes. |error| is the Win32 error code of the IO operation | 
| 232     // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero | 197     // (ERROR_SUCCESS if there was no error). |bytes_transfered| will be zero | 
| 233     // on error. | 198     // on error. | 
| 234     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, | 199     virtual void OnIOCompleted(IOContext* context, DWORD bytes_transfered, | 
| 235                                DWORD error) = 0; | 200                                DWORD error) = 0; | 
| 236   }; | 201   }; | 
| 237 | 202 | 
| 238   // The extended context that should be used as the base structure on every |  | 
| 239   // overlapped IO operation. |handler| must be set to the registered IOHandler |  | 
| 240   // for the given file when the operation is started, and it can be set to NULL |  | 
| 241   // before the operation completes to indicate that the handler should not be |  | 
| 242   // called anymore, and instead, the IOContext should be deleted when the OS |  | 
| 243   // notifies the completion of this operation. Please remember that any buffers |  | 
| 244   // involved with an IO operation should be around until the callback is |  | 
| 245   // received, so this technique can only be used for IO that do not involve |  | 
| 246   // additional buffers (other than the overlapped structure itself). |  | 
| 247   struct IOContext { |  | 
| 248     OVERLAPPED overlapped; |  | 
| 249     IOHandler* handler; |  | 
| 250   }; |  | 
| 251 |  | 
| 252   MessagePumpForIO(); | 203   MessagePumpForIO(); | 
| 253   ~MessagePumpForIO() override; | 204   ~MessagePumpForIO() override; | 
| 254 | 205 | 
| 255   // MessagePump methods: | 206   // MessagePump methods: | 
| 256   void ScheduleWork() override; | 207   void ScheduleWork() override; | 
| 257   void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; | 208   void ScheduleDelayedWork(const TimeTicks& delayed_work_time) override; | 
| 258 | 209 | 
| 259   // Register the handler to be used when asynchronous IO for the given file | 210   // Register the handler to be used when asynchronous IO for the given file | 
| 260   // completes. The registration persists as long as |file_handle| is valid, so | 211   // completes. The registration persists as long as |file_handle| is valid, so | 
| 261   // |handler| must be valid as long as there is pending IO for the given file. | 212   // |handler| must be valid as long as there is pending IO for the given file. | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 277   // External use of this method should be reserved for the rare case when the | 228   // External use of this method should be reserved for the rare case when the | 
| 278   // caller is willing to allow pausing regular task dispatching on this thread. | 229   // caller is willing to allow pausing regular task dispatching on this thread. | 
| 279   bool WaitForIOCompletion(DWORD timeout, IOHandler* filter); | 230   bool WaitForIOCompletion(DWORD timeout, IOHandler* filter); | 
| 280 | 231 | 
| 281  private: | 232  private: | 
| 282   struct IOItem { | 233   struct IOItem { | 
| 283     IOHandler* handler; | 234     IOHandler* handler; | 
| 284     IOContext* context; | 235     IOContext* context; | 
| 285     DWORD bytes_transfered; | 236     DWORD bytes_transfered; | 
| 286     DWORD error; | 237     DWORD error; | 
| 287 |  | 
| 288     // In some cases |context| can be a non-pointer value casted to a pointer. |  | 
| 289     // |has_valid_io_context| is true if |context| is a valid IOContext |  | 
| 290     // pointer, and false otherwise. |  | 
| 291     bool has_valid_io_context; |  | 
| 292   }; | 238   }; | 
| 293 | 239 | 
| 294   void DoRunLoop() override; | 240   void DoRunLoop() override; | 
| 295   void WaitForWork(); | 241   void WaitForWork(); | 
| 296   bool MatchCompletedIOItem(IOHandler* filter, IOItem* item); | 242   bool MatchCompletedIOItem(IOHandler* filter, IOItem* item); | 
| 297   bool GetIOItem(DWORD timeout, IOItem* item); | 243   bool GetIOItem(DWORD timeout, IOItem* item); | 
| 298   bool ProcessInternalIOItem(const IOItem& item); | 244   bool ProcessInternalIOItem(const IOItem& item); | 
| 299 | 245 | 
| 300   // Converts an IOHandler pointer to a completion port key. |  | 
| 301   // |has_valid_io_context| specifies whether completion packets posted to |  | 
| 302   // |handler| will have valid OVERLAPPED pointers. |  | 
| 303   static ULONG_PTR HandlerToKey(IOHandler* handler, bool has_valid_io_context); |  | 
| 304 |  | 
| 305   // Converts a completion port key to an IOHandler pointer. |  | 
| 306   static IOHandler* KeyToHandler(ULONG_PTR key, bool* has_valid_io_context); |  | 
| 307 |  | 
| 308   // The completion port associated with this thread. | 246   // The completion port associated with this thread. | 
| 309   win::ScopedHandle port_; | 247   win::ScopedHandle port_; | 
| 310   // This list will be empty almost always. It stores IO completions that have | 248   // This list will be empty almost always. It stores IO completions that have | 
| 311   // not been delivered yet because somebody was doing cleanup. | 249   // not been delivered yet because somebody was doing cleanup. | 
| 312   std::list<IOItem> completed_io_; | 250   std::list<IOItem> completed_io_; | 
| 313 }; | 251 }; | 
| 314 | 252 | 
| 315 }  // namespace base | 253 }  // namespace base | 
| 316 | 254 | 
| 317 #endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 255 #endif  // BASE_MESSAGE_LOOP_MESSAGE_PUMP_WIN_H_ | 
| OLD | NEW | 
|---|