|
|
|||
File indexing completed on 2026-04-17 08:35:04
0001 /* 0002 * Licensed to the Apache Software Foundation (ASF) under one 0003 * or more contributor license agreements. See the NOTICE file 0004 * distributed with this work for additional information 0005 * regarding copyright ownership. The ASF licenses this file 0006 * to you under the Apache License, Version 2.0 (the 0007 * "License"); you may not use this file except in compliance 0008 * with the License. You may obtain a copy of the License at 0009 * 0010 * http://www.apache.org/licenses/LICENSE-2.0 0011 * 0012 * Unless required by applicable law or agreed to in writing, 0013 * software distributed under the License is distributed on an 0014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 0015 * KIND, either express or implied. See the License for the 0016 * specific language governing permissions and limitations 0017 * under the License. 0018 */ 0019 0020 #ifndef _THRIFT_WINDOWS_OverlappedSubmissionThread_H_ 0021 #define _THRIFT_WINDOWS_OverlappedSubmissionThread_H_ 1 0022 0023 #ifndef _WIN32 0024 #error "OverlappedSubmissionThread.h is only usable on Windows" 0025 #endif 0026 0027 #include <thrift/windows/Sync.h> 0028 #include <thrift/TNonCopyable.h> 0029 0030 /* 0031 *** Why does this class exist? 0032 In short, because we want to enable something similar to a "select" loop, on Windows, with 0033 named pipes. The core of the "select" loop is a call to WaitForMultipleObjects. So that means 0034 we need a signalable object that indicates when data is available. 0035 0036 A pipe handle doesn't do that. A pipe handle is signaled when a read or write completes, and if 0037 no one has called read or write, then the pipe handle is useless in WaitForMultipleObjects. So 0038 instead, we use overlapped I/O. With overlapped I/O, you call read, and associate an event with 0039 the read. When the read finishes, the event is signaled. This means that when you create a pipe, 0040 you start a read. When the customer calls read on your transport object, you wait for the last 0041 read to finish, and then kick off another. 0042 0043 There is one big caveat to this though. The thread that initiated the read must stay alive. If 0044 the thread that initiated the read exits, then the read completes in an error state. To ensure 0045 that the initiating thread stays alive, we create a singleton thread whose sole responsibility is 0046 to manage this overlapped I/O requests. This introduces some overhead, but it is overhead that 0047 is necessary for correct behavior. 0048 0049 This thread currently supports connect, read, and cancel io. So far, I haven't needed to put any 0050 writes on this thread, but if needed, it could be done. The client write buffer would need to be 0051 copied to ensure that it doesn't get invalidated. 0052 0053 *** How does one use this class? 0054 Create a TOverlappedWorkItem, and fill in the action and "h", then call reset(). Your work item 0055 is now ready to be submitted to the overlapped submission thread. Create a TAutoOverlapThread, 0056 and call thread->addWorkItem with your work item. After addWorkItem completes, you may inspect 0057 last_error and success. At some point in the future, call workItem.overlappedResults to wait 0058 until the operation has completed. 0059 */ 0060 0061 namespace apache { 0062 namespace thrift { 0063 namespace transport { 0064 0065 struct DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) TOverlappedWorkItem : public SLIST_ENTRY { 0066 TOverlappedWorkItem(); 0067 0068 enum action_t { 0069 UNKNOWN = 3000, 0070 CONNECT, 0071 READ, 0072 CANCELIO, 0073 STOP, 0074 }; 0075 0076 TAutoResetEvent doneSubmittingEvent; 0077 action_t action; 0078 HANDLE h; 0079 uint8_t* buffer; 0080 uint32_t buffer_len; 0081 OVERLAPPED overlap; 0082 0083 DWORD last_error; 0084 BOOL success; 0085 0086 void reset(uint8_t* buf, uint32_t len, HANDLE event); 0087 uint32_t overlappedResults(bool signal_failure = true); 0088 bool process(); 0089 }; 0090 0091 class TOverlappedSubmissionThread : apache::thrift::TNonCopyable { 0092 public: 0093 void addWorkItem(TOverlappedWorkItem* item); 0094 0095 // singleton stuff 0096 public: 0097 static TOverlappedSubmissionThread* acquire_instance(); 0098 static void release_instance(); 0099 0100 private: 0101 static TCriticalSection instanceGuard_; 0102 static TOverlappedSubmissionThread* instance_; 0103 static uint32_t instanceRefCount_; 0104 0105 // thread details 0106 private: 0107 TOverlappedSubmissionThread(); 0108 virtual ~TOverlappedSubmissionThread(); 0109 void run(); 0110 static unsigned __stdcall thread_proc(void* addr); 0111 0112 private: 0113 DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) SLIST_HEADER workList_; 0114 TOverlappedWorkItem stopItem_; 0115 TAutoResetEvent workAvailableEvent_; 0116 HANDLE thread_; 0117 }; 0118 0119 class TAutoOverlapThread : apache::thrift::TNonCopyable { 0120 private: 0121 TOverlappedSubmissionThread* p; 0122 0123 public: 0124 TAutoOverlapThread() : p(TOverlappedSubmissionThread::acquire_instance()) {} 0125 virtual ~TAutoOverlapThread() { TOverlappedSubmissionThread::release_instance(); } 0126 TOverlappedSubmissionThread* operator->() { return p; } 0127 }; 0128 } 0129 } 0130 } // apache::thrift::transport 0131 0132 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|