File: | tools/lli/ChildTarget/ChildTarget.cpp |
Warning: | line 1151, column 14 1st function call argument is an uninitialized value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | #include "llvm/ExecutionEngine/Orc/OrcABISupport.h" | |||
2 | #include "llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h" | |||
3 | #include "llvm/Support/Debug.h" | |||
4 | #include "llvm/Support/DynamicLibrary.h" | |||
5 | #include "llvm/Support/Process.h" | |||
6 | #include <sstream> | |||
7 | ||||
8 | #include "../RemoteJITUtils.h" | |||
9 | ||||
10 | using namespace llvm; | |||
11 | using namespace llvm::orc; | |||
12 | using namespace llvm::sys; | |||
13 | ||||
14 | #ifdef __x86_64__1 | |||
15 | typedef OrcX86_64_SysV HostOrcArch; | |||
16 | #else | |||
17 | typedef OrcGenericABI HostOrcArch; | |||
18 | #endif | |||
19 | ||||
20 | ExitOnError ExitOnErr; | |||
21 | ||||
22 | int main(int argc, char *argv[]) { | |||
23 | ||||
24 | if (argc != 3) { | |||
| ||||
25 | errs() << "Usage: " << argv[0] << " <input fd> <output fd>\n"; | |||
26 | return 1; | |||
27 | } | |||
28 | ||||
29 | ExitOnErr.setBanner(std::string(argv[0]) + ":"); | |||
30 | ||||
31 | int InFD; | |||
32 | int OutFD; | |||
33 | { | |||
34 | std::istringstream InFDStream(argv[1]), OutFDStream(argv[2]); | |||
35 | InFDStream >> InFD; | |||
36 | OutFDStream >> OutFD; | |||
37 | } | |||
38 | ||||
39 | if (sys::DynamicLibrary::LoadLibraryPermanently(nullptr)) { | |||
40 | errs() << "Error loading program symbols.\n"; | |||
41 | return 1; | |||
42 | } | |||
43 | ||||
44 | auto SymbolLookup = [](const std::string &Name) { | |||
45 | return RTDyldMemoryManager::getSymbolAddressInProcess(Name); | |||
46 | }; | |||
47 | ||||
48 | auto RegisterEHFrames = [](uint8_t *Addr, uint32_t Size) { | |||
49 | RTDyldMemoryManager::registerEHFramesInProcess(Addr, Size); | |||
50 | }; | |||
51 | ||||
52 | auto DeregisterEHFrames = [](uint8_t *Addr, uint32_t Size) { | |||
53 | RTDyldMemoryManager::deregisterEHFramesInProcess(Addr, Size); | |||
54 | }; | |||
55 | ||||
56 | FDRawChannel Channel(InFD, OutFD); | |||
57 | typedef remote::OrcRemoteTargetServer<FDRawChannel, HostOrcArch> JITServer; | |||
58 | JITServer Server(Channel, SymbolLookup, RegisterEHFrames, DeregisterEHFrames); | |||
59 | ||||
60 | while (!Server.receivedTerminate()) | |||
61 | ExitOnErr(Server.handleOne()); | |||
62 | ||||
63 | close(InFD); | |||
64 | close(OutFD); | |||
65 | ||||
66 | return 0; | |||
67 | } |
1 | //===------- RPCUTils.h - Utilities for building RPC APIs -------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // Utilities to support construction of simple RPC APIs. | |||
11 | // | |||
12 | // The RPC utilities aim for ease of use (minimal conceptual overhead) for C++ | |||
13 | // programmers, high performance, low memory overhead, and efficient use of the | |||
14 | // communications channel. | |||
15 | // | |||
16 | //===----------------------------------------------------------------------===// | |||
17 | ||||
18 | #ifndef LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H | |||
19 | #define LLVM_EXECUTIONENGINE_ORC_RPCUTILS_H | |||
20 | ||||
21 | #include <map> | |||
22 | #include <thread> | |||
23 | #include <vector> | |||
24 | ||||
25 | #include "llvm/ADT/STLExtras.h" | |||
26 | #include "llvm/ExecutionEngine/Orc/OrcError.h" | |||
27 | #include "llvm/ExecutionEngine/Orc/RPCSerialization.h" | |||
28 | ||||
29 | #include <future> | |||
30 | ||||
31 | namespace llvm { | |||
32 | namespace orc { | |||
33 | namespace rpc { | |||
34 | ||||
35 | /// Base class of all fatal RPC errors (those that necessarily result in the | |||
36 | /// termination of the RPC session). | |||
37 | class RPCFatalError : public ErrorInfo<RPCFatalError> { | |||
38 | public: | |||
39 | static char ID; | |||
40 | }; | |||
41 | ||||
42 | /// RPCConnectionClosed is returned from RPC operations if the RPC connection | |||
43 | /// has already been closed due to either an error or graceful disconnection. | |||
44 | class ConnectionClosed : public ErrorInfo<ConnectionClosed> { | |||
45 | public: | |||
46 | static char ID; | |||
47 | std::error_code convertToErrorCode() const override; | |||
48 | void log(raw_ostream &OS) const override; | |||
49 | }; | |||
50 | ||||
51 | /// BadFunctionCall is returned from handleOne when the remote makes a call with | |||
52 | /// an unrecognized function id. | |||
53 | /// | |||
54 | /// This error is fatal because Orc RPC needs to know how to parse a function | |||
55 | /// call to know where the next call starts, and if it doesn't recognize the | |||
56 | /// function id it cannot parse the call. | |||
57 | template <typename FnIdT, typename SeqNoT> | |||
58 | class BadFunctionCall | |||
59 | : public ErrorInfo<BadFunctionCall<FnIdT, SeqNoT>, RPCFatalError> { | |||
60 | public: | |||
61 | static char ID; | |||
62 | ||||
63 | BadFunctionCall(FnIdT FnId, SeqNoT SeqNo) | |||
64 | : FnId(std::move(FnId)), SeqNo(std::move(SeqNo)) {} | |||
65 | ||||
66 | std::error_code convertToErrorCode() const override { | |||
67 | return orcError(OrcErrorCode::UnexpectedRPCCall); | |||
68 | } | |||
69 | ||||
70 | void log(raw_ostream &OS) const override { | |||
71 | OS << "Call to invalid RPC function id '" << FnId << "' with " | |||
72 | "sequence number " << SeqNo; | |||
73 | } | |||
74 | ||||
75 | private: | |||
76 | FnIdT FnId; | |||
77 | SeqNoT SeqNo; | |||
78 | }; | |||
79 | ||||
80 | template <typename FnIdT, typename SeqNoT> | |||
81 | char BadFunctionCall<FnIdT, SeqNoT>::ID = 0; | |||
82 | ||||
83 | /// InvalidSequenceNumberForResponse is returned from handleOne when a response | |||
84 | /// call arrives with a sequence number that doesn't correspond to any in-flight | |||
85 | /// function call. | |||
86 | /// | |||
87 | /// This error is fatal because Orc RPC needs to know how to parse the rest of | |||
88 | /// the response call to know where the next call starts, and if it doesn't have | |||
89 | /// a result parser for this sequence number it can't do that. | |||
90 | template <typename SeqNoT> | |||
91 | class InvalidSequenceNumberForResponse | |||
92 | : public ErrorInfo<InvalidSequenceNumberForResponse<SeqNoT>, RPCFatalError> { | |||
93 | public: | |||
94 | static char ID; | |||
95 | ||||
96 | InvalidSequenceNumberForResponse(SeqNoT SeqNo) | |||
97 | : SeqNo(std::move(SeqNo)) {} | |||
98 | ||||
99 | std::error_code convertToErrorCode() const override { | |||
100 | return orcError(OrcErrorCode::UnexpectedRPCCall); | |||
101 | }; | |||
102 | ||||
103 | void log(raw_ostream &OS) const override { | |||
104 | OS << "Response has unknown sequence number " << SeqNo; | |||
105 | } | |||
106 | private: | |||
107 | SeqNoT SeqNo; | |||
108 | }; | |||
109 | ||||
110 | template <typename SeqNoT> | |||
111 | char InvalidSequenceNumberForResponse<SeqNoT>::ID = 0; | |||
112 | ||||
113 | /// This non-fatal error will be passed to asynchronous result handlers in place | |||
114 | /// of a result if the connection goes down before a result returns, or if the | |||
115 | /// function to be called cannot be negotiated with the remote. | |||
116 | class ResponseAbandoned : public ErrorInfo<ResponseAbandoned> { | |||
117 | public: | |||
118 | static char ID; | |||
119 | ||||
120 | std::error_code convertToErrorCode() const override; | |||
121 | void log(raw_ostream &OS) const override; | |||
122 | }; | |||
123 | ||||
124 | /// This error is returned if the remote does not have a handler installed for | |||
125 | /// the given RPC function. | |||
126 | class CouldNotNegotiate : public ErrorInfo<CouldNotNegotiate> { | |||
127 | public: | |||
128 | static char ID; | |||
129 | ||||
130 | CouldNotNegotiate(std::string Signature); | |||
131 | std::error_code convertToErrorCode() const override; | |||
132 | void log(raw_ostream &OS) const override; | |||
133 | const std::string &getSignature() const { return Signature; } | |||
134 | private: | |||
135 | std::string Signature; | |||
136 | }; | |||
137 | ||||
138 | template <typename DerivedFunc, typename FnT> class Function; | |||
139 | ||||
140 | // RPC Function class. | |||
141 | // DerivedFunc should be a user defined class with a static 'getName()' method | |||
142 | // returning a const char* representing the function's name. | |||
143 | template <typename DerivedFunc, typename RetT, typename... ArgTs> | |||
144 | class Function<DerivedFunc, RetT(ArgTs...)> { | |||
145 | public: | |||
146 | /// User defined function type. | |||
147 | using Type = RetT(ArgTs...); | |||
148 | ||||
149 | /// Return type. | |||
150 | using ReturnType = RetT; | |||
151 | ||||
152 | /// Returns the full function prototype as a string. | |||
153 | static const char *getPrototype() { | |||
154 | std::lock_guard<std::mutex> Lock(NameMutex); | |||
155 | if (Name.empty()) | |||
156 | raw_string_ostream(Name) | |||
157 | << RPCTypeName<RetT>::getName() << " " << DerivedFunc::getName() | |||
158 | << "(" << llvm::orc::rpc::RPCTypeNameSequence<ArgTs...>() << ")"; | |||
159 | return Name.data(); | |||
160 | } | |||
161 | ||||
162 | private: | |||
163 | static std::mutex NameMutex; | |||
164 | static std::string Name; | |||
165 | }; | |||
166 | ||||
167 | template <typename DerivedFunc, typename RetT, typename... ArgTs> | |||
168 | std::mutex Function<DerivedFunc, RetT(ArgTs...)>::NameMutex; | |||
169 | ||||
170 | template <typename DerivedFunc, typename RetT, typename... ArgTs> | |||
171 | std::string Function<DerivedFunc, RetT(ArgTs...)>::Name; | |||
172 | ||||
173 | /// Allocates RPC function ids during autonegotiation. | |||
174 | /// Specializations of this class must provide four members: | |||
175 | /// | |||
176 | /// static T getInvalidId(): | |||
177 | /// Should return a reserved id that will be used to represent missing | |||
178 | /// functions during autonegotiation. | |||
179 | /// | |||
180 | /// static T getResponseId(): | |||
181 | /// Should return a reserved id that will be used to send function responses | |||
182 | /// (return values). | |||
183 | /// | |||
184 | /// static T getNegotiateId(): | |||
185 | /// Should return a reserved id for the negotiate function, which will be used | |||
186 | /// to negotiate ids for user defined functions. | |||
187 | /// | |||
188 | /// template <typename Func> T allocate(): | |||
189 | /// Allocate a unique id for function Func. | |||
190 | template <typename T, typename = void> class RPCFunctionIdAllocator; | |||
191 | ||||
192 | /// This specialization of RPCFunctionIdAllocator provides a default | |||
193 | /// implementation for integral types. | |||
194 | template <typename T> | |||
195 | class RPCFunctionIdAllocator< | |||
196 | T, typename std::enable_if<std::is_integral<T>::value>::type> { | |||
197 | public: | |||
198 | static T getInvalidId() { return T(0); } | |||
199 | static T getResponseId() { return T(1); } | |||
200 | static T getNegotiateId() { return T(2); } | |||
201 | ||||
202 | template <typename Func> T allocate() { return NextId++; } | |||
203 | ||||
204 | private: | |||
205 | T NextId = 3; | |||
206 | }; | |||
207 | ||||
208 | namespace detail { | |||
209 | ||||
210 | // FIXME: Remove MSVCPError/MSVCPExpected once MSVC's future implementation | |||
211 | // supports classes without default constructors. | |||
212 | #ifdef _MSC_VER | |||
213 | ||||
214 | namespace msvc_hacks { | |||
215 | ||||
216 | // Work around MSVC's future implementation's use of default constructors: | |||
217 | // A default constructed value in the promise will be overwritten when the | |||
218 | // real error is set - so the default constructed Error has to be checked | |||
219 | // already. | |||
220 | class MSVCPError : public Error { | |||
221 | public: | |||
222 | MSVCPError() { (void)!!*this; } | |||
223 | ||||
224 | MSVCPError(MSVCPError &&Other) : Error(std::move(Other)) {} | |||
225 | ||||
226 | MSVCPError &operator=(MSVCPError Other) { | |||
227 | Error::operator=(std::move(Other)); | |||
228 | return *this; | |||
229 | } | |||
230 | ||||
231 | MSVCPError(Error Err) : Error(std::move(Err)) {} | |||
232 | }; | |||
233 | ||||
234 | // Work around MSVC's future implementation, similar to MSVCPError. | |||
235 | template <typename T> class MSVCPExpected : public Expected<T> { | |||
236 | public: | |||
237 | MSVCPExpected() | |||
238 | : Expected<T>(make_error<StringError>("", inconvertibleErrorCode())) { | |||
239 | consumeError(this->takeError()); | |||
240 | } | |||
241 | ||||
242 | MSVCPExpected(MSVCPExpected &&Other) : Expected<T>(std::move(Other)) {} | |||
243 | ||||
244 | MSVCPExpected &operator=(MSVCPExpected &&Other) { | |||
245 | Expected<T>::operator=(std::move(Other)); | |||
246 | return *this; | |||
247 | } | |||
248 | ||||
249 | MSVCPExpected(Error Err) : Expected<T>(std::move(Err)) {} | |||
250 | ||||
251 | template <typename OtherT> | |||
252 | MSVCPExpected( | |||
253 | OtherT &&Val, | |||
254 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = | |||
255 | nullptr) | |||
256 | : Expected<T>(std::move(Val)) {} | |||
257 | ||||
258 | template <class OtherT> | |||
259 | MSVCPExpected( | |||
260 | Expected<OtherT> &&Other, | |||
261 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type * = | |||
262 | nullptr) | |||
263 | : Expected<T>(std::move(Other)) {} | |||
264 | ||||
265 | template <class OtherT> | |||
266 | explicit MSVCPExpected( | |||
267 | Expected<OtherT> &&Other, | |||
268 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = | |||
269 | nullptr) | |||
270 | : Expected<T>(std::move(Other)) {} | |||
271 | }; | |||
272 | ||||
273 | } // end namespace msvc_hacks | |||
274 | ||||
275 | #endif // _MSC_VER | |||
276 | ||||
277 | /// Provides a typedef for a tuple containing the decayed argument types. | |||
278 | template <typename T> class FunctionArgsTuple; | |||
279 | ||||
280 | template <typename RetT, typename... ArgTs> | |||
281 | class FunctionArgsTuple<RetT(ArgTs...)> { | |||
282 | public: | |||
283 | using Type = std::tuple<typename std::decay< | |||
284 | typename std::remove_reference<ArgTs>::type>::type...>; | |||
285 | }; | |||
286 | ||||
287 | // ResultTraits provides typedefs and utilities specific to the return type | |||
288 | // of functions. | |||
289 | template <typename RetT> class ResultTraits { | |||
290 | public: | |||
291 | // The return type wrapped in llvm::Expected. | |||
292 | using ErrorReturnType = Expected<RetT>; | |||
293 | ||||
294 | #ifdef _MSC_VER | |||
295 | // The ErrorReturnType wrapped in a std::promise. | |||
296 | using ReturnPromiseType = std::promise<msvc_hacks::MSVCPExpected<RetT>>; | |||
297 | ||||
298 | // The ErrorReturnType wrapped in a std::future. | |||
299 | using ReturnFutureType = std::future<msvc_hacks::MSVCPExpected<RetT>>; | |||
300 | #else | |||
301 | // The ErrorReturnType wrapped in a std::promise. | |||
302 | using ReturnPromiseType = std::promise<ErrorReturnType>; | |||
303 | ||||
304 | // The ErrorReturnType wrapped in a std::future. | |||
305 | using ReturnFutureType = std::future<ErrorReturnType>; | |||
306 | #endif | |||
307 | ||||
308 | // Create a 'blank' value of the ErrorReturnType, ready and safe to | |||
309 | // overwrite. | |||
310 | static ErrorReturnType createBlankErrorReturnValue() { | |||
311 | return ErrorReturnType(RetT()); | |||
312 | } | |||
313 | ||||
314 | // Consume an abandoned ErrorReturnType. | |||
315 | static void consumeAbandoned(ErrorReturnType RetOrErr) { | |||
316 | consumeError(RetOrErr.takeError()); | |||
317 | } | |||
318 | }; | |||
319 | ||||
320 | // ResultTraits specialization for void functions. | |||
321 | template <> class ResultTraits<void> { | |||
322 | public: | |||
323 | // For void functions, ErrorReturnType is llvm::Error. | |||
324 | using ErrorReturnType = Error; | |||
325 | ||||
326 | #ifdef _MSC_VER | |||
327 | // The ErrorReturnType wrapped in a std::promise. | |||
328 | using ReturnPromiseType = std::promise<msvc_hacks::MSVCPError>; | |||
329 | ||||
330 | // The ErrorReturnType wrapped in a std::future. | |||
331 | using ReturnFutureType = std::future<msvc_hacks::MSVCPError>; | |||
332 | #else | |||
333 | // The ErrorReturnType wrapped in a std::promise. | |||
334 | using ReturnPromiseType = std::promise<ErrorReturnType>; | |||
335 | ||||
336 | // The ErrorReturnType wrapped in a std::future. | |||
337 | using ReturnFutureType = std::future<ErrorReturnType>; | |||
338 | #endif | |||
339 | ||||
340 | // Create a 'blank' value of the ErrorReturnType, ready and safe to | |||
341 | // overwrite. | |||
342 | static ErrorReturnType createBlankErrorReturnValue() { | |||
343 | return ErrorReturnType::success(); | |||
344 | } | |||
345 | ||||
346 | // Consume an abandoned ErrorReturnType. | |||
347 | static void consumeAbandoned(ErrorReturnType Err) { | |||
348 | consumeError(std::move(Err)); | |||
349 | } | |||
350 | }; | |||
351 | ||||
352 | // ResultTraits<Error> is equivalent to ResultTraits<void>. This allows | |||
353 | // handlers for void RPC functions to return either void (in which case they | |||
354 | // implicitly succeed) or Error (in which case their error return is | |||
355 | // propagated). See usage in HandlerTraits::runHandlerHelper. | |||
356 | template <> class ResultTraits<Error> : public ResultTraits<void> {}; | |||
357 | ||||
358 | // ResultTraits<Expected<T>> is equivalent to ResultTraits<T>. This allows | |||
359 | // handlers for RPC functions returning a T to return either a T (in which | |||
360 | // case they implicitly succeed) or Expected<T> (in which case their error | |||
361 | // return is propagated). See usage in HandlerTraits::runHandlerHelper. | |||
362 | template <typename RetT> | |||
363 | class ResultTraits<Expected<RetT>> : public ResultTraits<RetT> {}; | |||
364 | ||||
365 | // Determines whether an RPC function's defined error return type supports | |||
366 | // error return value. | |||
367 | template <typename T> | |||
368 | class SupportsErrorReturn { | |||
369 | public: | |||
370 | static const bool value = false; | |||
371 | }; | |||
372 | ||||
373 | template <> | |||
374 | class SupportsErrorReturn<Error> { | |||
375 | public: | |||
376 | static const bool value = true; | |||
377 | }; | |||
378 | ||||
379 | template <typename T> | |||
380 | class SupportsErrorReturn<Expected<T>> { | |||
381 | public: | |||
382 | static const bool value = true; | |||
383 | }; | |||
384 | ||||
385 | // RespondHelper packages return values based on whether or not the declared | |||
386 | // RPC function return type supports error returns. | |||
387 | template <bool FuncSupportsErrorReturn> | |||
388 | class RespondHelper; | |||
389 | ||||
390 | // RespondHelper specialization for functions that support error returns. | |||
391 | template <> | |||
392 | class RespondHelper<true> { | |||
393 | public: | |||
394 | ||||
395 | // Send Expected<T>. | |||
396 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, | |||
397 | typename FunctionIdT, typename SequenceNumberT> | |||
398 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, | |||
399 | SequenceNumberT SeqNo, | |||
400 | Expected<HandlerRetT> ResultOrErr) { | |||
401 | if (!ResultOrErr && ResultOrErr.template errorIsA<RPCFatalError>()) | |||
402 | return ResultOrErr.takeError(); | |||
403 | ||||
404 | // Open the response message. | |||
405 | if (auto Err = C.startSendMessage(ResponseId, SeqNo)) | |||
406 | return Err; | |||
407 | ||||
408 | // Serialize the result. | |||
409 | if (auto Err = | |||
410 | SerializationTraits<ChannelT, WireRetT, | |||
411 | Expected<HandlerRetT>>::serialize( | |||
412 | C, std::move(ResultOrErr))) | |||
413 | return Err; | |||
414 | ||||
415 | // Close the response message. | |||
416 | return C.endSendMessage(); | |||
417 | } | |||
418 | ||||
419 | template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT> | |||
420 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, | |||
421 | SequenceNumberT SeqNo, Error Err) { | |||
422 | if (Err && Err.isA<RPCFatalError>()) | |||
423 | return Err; | |||
424 | if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) | |||
425 | return Err2; | |||
426 | if (auto Err2 = serializeSeq(C, std::move(Err))) | |||
427 | return Err2; | |||
428 | return C.endSendMessage(); | |||
429 | } | |||
430 | ||||
431 | }; | |||
432 | ||||
433 | // RespondHelper specialization for functions that do not support error returns. | |||
434 | template <> | |||
435 | class RespondHelper<false> { | |||
436 | public: | |||
437 | ||||
438 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, | |||
439 | typename FunctionIdT, typename SequenceNumberT> | |||
440 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, | |||
441 | SequenceNumberT SeqNo, | |||
442 | Expected<HandlerRetT> ResultOrErr) { | |||
443 | if (auto Err = ResultOrErr.takeError()) | |||
444 | return Err; | |||
445 | ||||
446 | // Open the response message. | |||
447 | if (auto Err = C.startSendMessage(ResponseId, SeqNo)) | |||
448 | return Err; | |||
449 | ||||
450 | // Serialize the result. | |||
451 | if (auto Err = | |||
452 | SerializationTraits<ChannelT, WireRetT, HandlerRetT>::serialize( | |||
453 | C, *ResultOrErr)) | |||
454 | return Err; | |||
455 | ||||
456 | // Close the response message. | |||
457 | return C.endSendMessage(); | |||
458 | } | |||
459 | ||||
460 | template <typename ChannelT, typename FunctionIdT, typename SequenceNumberT> | |||
461 | static Error sendResult(ChannelT &C, const FunctionIdT &ResponseId, | |||
462 | SequenceNumberT SeqNo, Error Err) { | |||
463 | if (Err) | |||
464 | return Err; | |||
465 | if (auto Err2 = C.startSendMessage(ResponseId, SeqNo)) | |||
466 | return Err2; | |||
467 | return C.endSendMessage(); | |||
468 | } | |||
469 | ||||
470 | }; | |||
471 | ||||
472 | ||||
473 | // Send a response of the given wire return type (WireRetT) over the | |||
474 | // channel, with the given sequence number. | |||
475 | template <typename WireRetT, typename HandlerRetT, typename ChannelT, | |||
476 | typename FunctionIdT, typename SequenceNumberT> | |||
477 | Error respond(ChannelT &C, const FunctionIdT &ResponseId, | |||
478 | SequenceNumberT SeqNo, Expected<HandlerRetT> ResultOrErr) { | |||
479 | return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: | |||
480 | template sendResult<WireRetT>(C, ResponseId, SeqNo, std::move(ResultOrErr)); | |||
481 | } | |||
482 | ||||
483 | // Send an empty response message on the given channel to indicate that | |||
484 | // the handler ran. | |||
485 | template <typename WireRetT, typename ChannelT, typename FunctionIdT, | |||
486 | typename SequenceNumberT> | |||
487 | Error respond(ChannelT &C, const FunctionIdT &ResponseId, SequenceNumberT SeqNo, | |||
488 | Error Err) { | |||
489 | return RespondHelper<SupportsErrorReturn<WireRetT>::value>:: | |||
490 | sendResult(C, ResponseId, SeqNo, std::move(Err)); | |||
491 | } | |||
492 | ||||
493 | // Converts a given type to the equivalent error return type. | |||
494 | template <typename T> class WrappedHandlerReturn { | |||
495 | public: | |||
496 | using Type = Expected<T>; | |||
497 | }; | |||
498 | ||||
499 | template <typename T> class WrappedHandlerReturn<Expected<T>> { | |||
500 | public: | |||
501 | using Type = Expected<T>; | |||
502 | }; | |||
503 | ||||
504 | template <> class WrappedHandlerReturn<void> { | |||
505 | public: | |||
506 | using Type = Error; | |||
507 | }; | |||
508 | ||||
509 | template <> class WrappedHandlerReturn<Error> { | |||
510 | public: | |||
511 | using Type = Error; | |||
512 | }; | |||
513 | ||||
514 | template <> class WrappedHandlerReturn<ErrorSuccess> { | |||
515 | public: | |||
516 | using Type = Error; | |||
517 | }; | |||
518 | ||||
519 | // Traits class that strips the response function from the list of handler | |||
520 | // arguments. | |||
521 | template <typename FnT> class AsyncHandlerTraits; | |||
522 | ||||
523 | template <typename ResultT, typename... ArgTs> | |||
524 | class AsyncHandlerTraits<Error(std::function<Error(Expected<ResultT>)>, ArgTs...)> { | |||
525 | public: | |||
526 | using Type = Error(ArgTs...); | |||
527 | using ResultType = Expected<ResultT>; | |||
528 | }; | |||
529 | ||||
530 | template <typename... ArgTs> | |||
531 | class AsyncHandlerTraits<Error(std::function<Error(Error)>, ArgTs...)> { | |||
532 | public: | |||
533 | using Type = Error(ArgTs...); | |||
534 | using ResultType = Error; | |||
535 | }; | |||
536 | ||||
537 | template <typename... ArgTs> | |||
538 | class AsyncHandlerTraits<ErrorSuccess(std::function<Error(Error)>, ArgTs...)> { | |||
539 | public: | |||
540 | using Type = Error(ArgTs...); | |||
541 | using ResultType = Error; | |||
542 | }; | |||
543 | ||||
544 | template <typename... ArgTs> | |||
545 | class AsyncHandlerTraits<void(std::function<Error(Error)>, ArgTs...)> { | |||
546 | public: | |||
547 | using Type = Error(ArgTs...); | |||
548 | using ResultType = Error; | |||
549 | }; | |||
550 | ||||
551 | template <typename ResponseHandlerT, typename... ArgTs> | |||
552 | class AsyncHandlerTraits<Error(ResponseHandlerT, ArgTs...)> : | |||
553 | public AsyncHandlerTraits<Error(typename std::decay<ResponseHandlerT>::type, | |||
554 | ArgTs...)> {}; | |||
555 | ||||
556 | // This template class provides utilities related to RPC function handlers. | |||
557 | // The base case applies to non-function types (the template class is | |||
558 | // specialized for function types) and inherits from the appropriate | |||
559 | // speciilization for the given non-function type's call operator. | |||
560 | template <typename HandlerT> | |||
561 | class HandlerTraits : public HandlerTraits<decltype( | |||
562 | &std::remove_reference<HandlerT>::type::operator())> { | |||
563 | }; | |||
564 | ||||
565 | // Traits for handlers with a given function type. | |||
566 | template <typename RetT, typename... ArgTs> | |||
567 | class HandlerTraits<RetT(ArgTs...)> { | |||
568 | public: | |||
569 | // Function type of the handler. | |||
570 | using Type = RetT(ArgTs...); | |||
571 | ||||
572 | // Return type of the handler. | |||
573 | using ReturnType = RetT; | |||
574 | ||||
575 | // Call the given handler with the given arguments. | |||
576 | template <typename HandlerT, typename... TArgTs> | |||
577 | static typename WrappedHandlerReturn<RetT>::Type | |||
578 | unpackAndRun(HandlerT &Handler, std::tuple<TArgTs...> &Args) { | |||
579 | return unpackAndRunHelper(Handler, Args, | |||
580 | llvm::index_sequence_for<TArgTs...>()); | |||
581 | } | |||
582 | ||||
583 | // Call the given handler with the given arguments. | |||
584 | template <typename HandlerT, typename ResponderT, typename... TArgTs> | |||
585 | static Error unpackAndRunAsync(HandlerT &Handler, ResponderT &Responder, | |||
586 | std::tuple<TArgTs...> &Args) { | |||
587 | return unpackAndRunAsyncHelper(Handler, Responder, Args, | |||
588 | llvm::index_sequence_for<TArgTs...>()); | |||
589 | } | |||
590 | ||||
591 | // Call the given handler with the given arguments. | |||
592 | template <typename HandlerT> | |||
593 | static typename std::enable_if< | |||
594 | std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, | |||
595 | Error>::type | |||
596 | run(HandlerT &Handler, ArgTs &&... Args) { | |||
597 | Handler(std::move(Args)...); | |||
598 | return Error::success(); | |||
599 | } | |||
600 | ||||
601 | template <typename HandlerT, typename... TArgTs> | |||
602 | static typename std::enable_if< | |||
603 | !std::is_void<typename HandlerTraits<HandlerT>::ReturnType>::value, | |||
604 | typename HandlerTraits<HandlerT>::ReturnType>::type | |||
605 | run(HandlerT &Handler, TArgTs... Args) { | |||
606 | return Handler(std::move(Args)...); | |||
607 | } | |||
608 | ||||
609 | // Serialize arguments to the channel. | |||
610 | template <typename ChannelT, typename... CArgTs> | |||
611 | static Error serializeArgs(ChannelT &C, const CArgTs... CArgs) { | |||
612 | return SequenceSerialization<ChannelT, ArgTs...>::serialize(C, CArgs...); | |||
613 | } | |||
614 | ||||
615 | // Deserialize arguments from the channel. | |||
616 | template <typename ChannelT, typename... CArgTs> | |||
617 | static Error deserializeArgs(ChannelT &C, std::tuple<CArgTs...> &Args) { | |||
618 | return deserializeArgsHelper(C, Args, | |||
619 | llvm::index_sequence_for<CArgTs...>()); | |||
620 | } | |||
621 | ||||
622 | private: | |||
623 | template <typename ChannelT, typename... CArgTs, size_t... Indexes> | |||
624 | static Error deserializeArgsHelper(ChannelT &C, std::tuple<CArgTs...> &Args, | |||
625 | llvm::index_sequence<Indexes...> _) { | |||
626 | return SequenceSerialization<ChannelT, ArgTs...>::deserialize( | |||
627 | C, std::get<Indexes>(Args)...); | |||
628 | } | |||
629 | ||||
630 | template <typename HandlerT, typename ArgTuple, size_t... Indexes> | |||
631 | static typename WrappedHandlerReturn< | |||
632 | typename HandlerTraits<HandlerT>::ReturnType>::Type | |||
633 | unpackAndRunHelper(HandlerT &Handler, ArgTuple &Args, | |||
634 | llvm::index_sequence<Indexes...>) { | |||
635 | return run(Handler, std::move(std::get<Indexes>(Args))...); | |||
636 | } | |||
637 | ||||
638 | ||||
639 | template <typename HandlerT, typename ResponderT, typename ArgTuple, | |||
640 | size_t... Indexes> | |||
641 | static typename WrappedHandlerReturn< | |||
642 | typename HandlerTraits<HandlerT>::ReturnType>::Type | |||
643 | unpackAndRunAsyncHelper(HandlerT &Handler, ResponderT &Responder, | |||
644 | ArgTuple &Args, | |||
645 | llvm::index_sequence<Indexes...>) { | |||
646 | return run(Handler, Responder, std::move(std::get<Indexes>(Args))...); | |||
647 | } | |||
648 | }; | |||
649 | ||||
650 | // Handler traits for free functions. | |||
651 | template <typename RetT, typename... ArgTs> | |||
652 | class HandlerTraits<RetT(*)(ArgTs...)> | |||
653 | : public HandlerTraits<RetT(ArgTs...)> {}; | |||
654 | ||||
655 | // Handler traits for class methods (especially call operators for lambdas). | |||
656 | template <typename Class, typename RetT, typename... ArgTs> | |||
657 | class HandlerTraits<RetT (Class::*)(ArgTs...)> | |||
658 | : public HandlerTraits<RetT(ArgTs...)> {}; | |||
659 | ||||
660 | // Handler traits for const class methods (especially call operators for | |||
661 | // lambdas). | |||
662 | template <typename Class, typename RetT, typename... ArgTs> | |||
663 | class HandlerTraits<RetT (Class::*)(ArgTs...) const> | |||
664 | : public HandlerTraits<RetT(ArgTs...)> {}; | |||
665 | ||||
666 | // Utility to peel the Expected wrapper off a response handler error type. | |||
667 | template <typename HandlerT> class ResponseHandlerArg; | |||
668 | ||||
669 | template <typename ArgT> class ResponseHandlerArg<Error(Expected<ArgT>)> { | |||
670 | public: | |||
671 | using ArgType = Expected<ArgT>; | |||
672 | using UnwrappedArgType = ArgT; | |||
673 | }; | |||
674 | ||||
675 | template <typename ArgT> | |||
676 | class ResponseHandlerArg<ErrorSuccess(Expected<ArgT>)> { | |||
677 | public: | |||
678 | using ArgType = Expected<ArgT>; | |||
679 | using UnwrappedArgType = ArgT; | |||
680 | }; | |||
681 | ||||
682 | template <> class ResponseHandlerArg<Error(Error)> { | |||
683 | public: | |||
684 | using ArgType = Error; | |||
685 | }; | |||
686 | ||||
687 | template <> class ResponseHandlerArg<ErrorSuccess(Error)> { | |||
688 | public: | |||
689 | using ArgType = Error; | |||
690 | }; | |||
691 | ||||
692 | // ResponseHandler represents a handler for a not-yet-received function call | |||
693 | // result. | |||
694 | template <typename ChannelT> class ResponseHandler { | |||
695 | public: | |||
696 | virtual ~ResponseHandler() {} | |||
697 | ||||
698 | // Reads the function result off the wire and acts on it. The meaning of | |||
699 | // "act" will depend on how this method is implemented in any given | |||
700 | // ResponseHandler subclass but could, for example, mean running a | |||
701 | // user-specified handler or setting a promise value. | |||
702 | virtual Error handleResponse(ChannelT &C) = 0; | |||
703 | ||||
704 | // Abandons this outstanding result. | |||
705 | virtual void abandon() = 0; | |||
706 | ||||
707 | // Create an error instance representing an abandoned response. | |||
708 | static Error createAbandonedResponseError() { | |||
709 | return make_error<ResponseAbandoned>(); | |||
710 | } | |||
711 | }; | |||
712 | ||||
713 | // ResponseHandler subclass for RPC functions with non-void returns. | |||
714 | template <typename ChannelT, typename FuncRetT, typename HandlerT> | |||
715 | class ResponseHandlerImpl : public ResponseHandler<ChannelT> { | |||
716 | public: | |||
717 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} | |||
718 | ||||
719 | // Handle the result by deserializing it from the channel then passing it | |||
720 | // to the user defined handler. | |||
721 | Error handleResponse(ChannelT &C) override { | |||
722 | using UnwrappedArgType = typename ResponseHandlerArg< | |||
723 | typename HandlerTraits<HandlerT>::Type>::UnwrappedArgType; | |||
724 | UnwrappedArgType Result; | |||
725 | if (auto Err = | |||
726 | SerializationTraits<ChannelT, FuncRetT, | |||
727 | UnwrappedArgType>::deserialize(C, Result)) | |||
728 | return Err; | |||
729 | if (auto Err = C.endReceiveMessage()) | |||
730 | return Err; | |||
731 | return Handler(std::move(Result)); | |||
732 | } | |||
733 | ||||
734 | // Abandon this response by calling the handler with an 'abandoned response' | |||
735 | // error. | |||
736 | void abandon() override { | |||
737 | if (auto Err = Handler(this->createAbandonedResponseError())) { | |||
738 | // Handlers should not fail when passed an abandoned response error. | |||
739 | report_fatal_error(std::move(Err)); | |||
740 | } | |||
741 | } | |||
742 | ||||
743 | private: | |||
744 | HandlerT Handler; | |||
745 | }; | |||
746 | ||||
747 | // ResponseHandler subclass for RPC functions with void returns. | |||
748 | template <typename ChannelT, typename HandlerT> | |||
749 | class ResponseHandlerImpl<ChannelT, void, HandlerT> | |||
750 | : public ResponseHandler<ChannelT> { | |||
751 | public: | |||
752 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} | |||
753 | ||||
754 | // Handle the result (no actual value, just a notification that the function | |||
755 | // has completed on the remote end) by calling the user-defined handler with | |||
756 | // Error::success(). | |||
757 | Error handleResponse(ChannelT &C) override { | |||
758 | if (auto Err = C.endReceiveMessage()) | |||
759 | return Err; | |||
760 | return Handler(Error::success()); | |||
761 | } | |||
762 | ||||
763 | // Abandon this response by calling the handler with an 'abandoned response' | |||
764 | // error. | |||
765 | void abandon() override { | |||
766 | if (auto Err = Handler(this->createAbandonedResponseError())) { | |||
767 | // Handlers should not fail when passed an abandoned response error. | |||
768 | report_fatal_error(std::move(Err)); | |||
769 | } | |||
770 | } | |||
771 | ||||
772 | private: | |||
773 | HandlerT Handler; | |||
774 | }; | |||
775 | ||||
776 | template <typename ChannelT, typename FuncRetT, typename HandlerT> | |||
777 | class ResponseHandlerImpl<ChannelT, Expected<FuncRetT>, HandlerT> | |||
778 | : public ResponseHandler<ChannelT> { | |||
779 | public: | |||
780 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} | |||
781 | ||||
782 | // Handle the result by deserializing it from the channel then passing it | |||
783 | // to the user defined handler. | |||
784 | Error handleResponse(ChannelT &C) override { | |||
785 | using HandlerArgType = typename ResponseHandlerArg< | |||
786 | typename HandlerTraits<HandlerT>::Type>::ArgType; | |||
787 | HandlerArgType Result((typename HandlerArgType::value_type())); | |||
788 | ||||
789 | if (auto Err = | |||
790 | SerializationTraits<ChannelT, Expected<FuncRetT>, | |||
791 | HandlerArgType>::deserialize(C, Result)) | |||
792 | return Err; | |||
793 | if (auto Err = C.endReceiveMessage()) | |||
794 | return Err; | |||
795 | return Handler(std::move(Result)); | |||
796 | } | |||
797 | ||||
798 | // Abandon this response by calling the handler with an 'abandoned response' | |||
799 | // error. | |||
800 | void abandon() override { | |||
801 | if (auto Err = Handler(this->createAbandonedResponseError())) { | |||
802 | // Handlers should not fail when passed an abandoned response error. | |||
803 | report_fatal_error(std::move(Err)); | |||
804 | } | |||
805 | } | |||
806 | ||||
807 | private: | |||
808 | HandlerT Handler; | |||
809 | }; | |||
810 | ||||
811 | template <typename ChannelT, typename HandlerT> | |||
812 | class ResponseHandlerImpl<ChannelT, Error, HandlerT> | |||
813 | : public ResponseHandler<ChannelT> { | |||
814 | public: | |||
815 | ResponseHandlerImpl(HandlerT Handler) : Handler(std::move(Handler)) {} | |||
816 | ||||
817 | // Handle the result by deserializing it from the channel then passing it | |||
818 | // to the user defined handler. | |||
819 | Error handleResponse(ChannelT &C) override { | |||
820 | Error Result = Error::success(); | |||
821 | if (auto Err = | |||
822 | SerializationTraits<ChannelT, Error, Error>::deserialize(C, Result)) | |||
823 | return Err; | |||
824 | if (auto Err = C.endReceiveMessage()) | |||
825 | return Err; | |||
826 | return Handler(std::move(Result)); | |||
827 | } | |||
828 | ||||
829 | // Abandon this response by calling the handler with an 'abandoned response' | |||
830 | // error. | |||
831 | void abandon() override { | |||
832 | if (auto Err = Handler(this->createAbandonedResponseError())) { | |||
833 | // Handlers should not fail when passed an abandoned response error. | |||
834 | report_fatal_error(std::move(Err)); | |||
835 | } | |||
836 | } | |||
837 | ||||
838 | private: | |||
839 | HandlerT Handler; | |||
840 | }; | |||
841 | ||||
842 | // Create a ResponseHandler from a given user handler. | |||
843 | template <typename ChannelT, typename FuncRetT, typename HandlerT> | |||
844 | std::unique_ptr<ResponseHandler<ChannelT>> createResponseHandler(HandlerT H) { | |||
845 | return llvm::make_unique<ResponseHandlerImpl<ChannelT, FuncRetT, HandlerT>>( | |||
846 | std::move(H)); | |||
847 | } | |||
848 | ||||
849 | // Helper for wrapping member functions up as functors. This is useful for | |||
850 | // installing methods as result handlers. | |||
851 | template <typename ClassT, typename RetT, typename... ArgTs> | |||
852 | class MemberFnWrapper { | |||
853 | public: | |||
854 | using MethodT = RetT (ClassT::*)(ArgTs...); | |||
855 | MemberFnWrapper(ClassT &Instance, MethodT Method) | |||
856 | : Instance(Instance), Method(Method) {} | |||
857 | RetT operator()(ArgTs &&... Args) { | |||
858 | return (Instance.*Method)(std::move(Args)...); | |||
859 | } | |||
860 | ||||
861 | private: | |||
862 | ClassT &Instance; | |||
863 | MethodT Method; | |||
864 | }; | |||
865 | ||||
866 | // Helper that provides a Functor for deserializing arguments. | |||
867 | template <typename... ArgTs> class ReadArgs { | |||
868 | public: | |||
869 | Error operator()() { return Error::success(); } | |||
870 | }; | |||
871 | ||||
872 | template <typename ArgT, typename... ArgTs> | |||
873 | class ReadArgs<ArgT, ArgTs...> : public ReadArgs<ArgTs...> { | |||
874 | public: | |||
875 | ReadArgs(ArgT &Arg, ArgTs &... Args) | |||
876 | : ReadArgs<ArgTs...>(Args...), Arg(Arg) {} | |||
877 | ||||
878 | Error operator()(ArgT &ArgVal, ArgTs &... ArgVals) { | |||
879 | this->Arg = std::move(ArgVal); | |||
880 | return ReadArgs<ArgTs...>::operator()(ArgVals...); | |||
881 | } | |||
882 | ||||
883 | private: | |||
884 | ArgT &Arg; | |||
885 | }; | |||
886 | ||||
887 | // Manage sequence numbers. | |||
888 | template <typename SequenceNumberT> class SequenceNumberManager { | |||
889 | public: | |||
890 | // Reset, making all sequence numbers available. | |||
891 | void reset() { | |||
892 | std::lock_guard<std::mutex> Lock(SeqNoLock); | |||
893 | NextSequenceNumber = 0; | |||
894 | FreeSequenceNumbers.clear(); | |||
895 | } | |||
896 | ||||
897 | // Get the next available sequence number. Will re-use numbers that have | |||
898 | // been released. | |||
899 | SequenceNumberT getSequenceNumber() { | |||
900 | std::lock_guard<std::mutex> Lock(SeqNoLock); | |||
901 | if (FreeSequenceNumbers.empty()) | |||
902 | return NextSequenceNumber++; | |||
903 | auto SequenceNumber = FreeSequenceNumbers.back(); | |||
904 | FreeSequenceNumbers.pop_back(); | |||
905 | return SequenceNumber; | |||
906 | } | |||
907 | ||||
908 | // Release a sequence number, making it available for re-use. | |||
909 | void releaseSequenceNumber(SequenceNumberT SequenceNumber) { | |||
910 | std::lock_guard<std::mutex> Lock(SeqNoLock); | |||
911 | FreeSequenceNumbers.push_back(SequenceNumber); | |||
912 | } | |||
913 | ||||
914 | private: | |||
915 | std::mutex SeqNoLock; | |||
916 | SequenceNumberT NextSequenceNumber = 0; | |||
917 | std::vector<SequenceNumberT> FreeSequenceNumbers; | |||
918 | }; | |||
919 | ||||
920 | // Checks that predicate P holds for each corresponding pair of type arguments | |||
921 | // from T1 and T2 tuple. | |||
922 | template <template <class, class> class P, typename T1Tuple, typename T2Tuple> | |||
923 | class RPCArgTypeCheckHelper; | |||
924 | ||||
925 | template <template <class, class> class P> | |||
926 | class RPCArgTypeCheckHelper<P, std::tuple<>, std::tuple<>> { | |||
927 | public: | |||
928 | static const bool value = true; | |||
929 | }; | |||
930 | ||||
931 | template <template <class, class> class P, typename T, typename... Ts, | |||
932 | typename U, typename... Us> | |||
933 | class RPCArgTypeCheckHelper<P, std::tuple<T, Ts...>, std::tuple<U, Us...>> { | |||
934 | public: | |||
935 | static const bool value = | |||
936 | P<T, U>::value && | |||
937 | RPCArgTypeCheckHelper<P, std::tuple<Ts...>, std::tuple<Us...>>::value; | |||
938 | }; | |||
939 | ||||
940 | template <template <class, class> class P, typename T1Sig, typename T2Sig> | |||
941 | class RPCArgTypeCheck { | |||
942 | public: | |||
943 | using T1Tuple = typename FunctionArgsTuple<T1Sig>::Type; | |||
944 | using T2Tuple = typename FunctionArgsTuple<T2Sig>::Type; | |||
945 | ||||
946 | static_assert(std::tuple_size<T1Tuple>::value >= | |||
947 | std::tuple_size<T2Tuple>::value, | |||
948 | "Too many arguments to RPC call"); | |||
949 | static_assert(std::tuple_size<T1Tuple>::value <= | |||
950 | std::tuple_size<T2Tuple>::value, | |||
951 | "Too few arguments to RPC call"); | |||
952 | ||||
953 | static const bool value = RPCArgTypeCheckHelper<P, T1Tuple, T2Tuple>::value; | |||
954 | }; | |||
955 | ||||
956 | template <typename ChannelT, typename WireT, typename ConcreteT> | |||
957 | class CanSerialize { | |||
958 | private: | |||
959 | using S = SerializationTraits<ChannelT, WireT, ConcreteT>; | |||
960 | ||||
961 | template <typename T> | |||
962 | static std::true_type | |||
963 | check(typename std::enable_if< | |||
964 | std::is_same<decltype(T::serialize(std::declval<ChannelT &>(), | |||
965 | std::declval<const ConcreteT &>())), | |||
966 | Error>::value, | |||
967 | void *>::type); | |||
968 | ||||
969 | template <typename> static std::false_type check(...); | |||
970 | ||||
971 | public: | |||
972 | static const bool value = decltype(check<S>(0))::value; | |||
973 | }; | |||
974 | ||||
975 | template <typename ChannelT, typename WireT, typename ConcreteT> | |||
976 | class CanDeserialize { | |||
977 | private: | |||
978 | using S = SerializationTraits<ChannelT, WireT, ConcreteT>; | |||
979 | ||||
980 | template <typename T> | |||
981 | static std::true_type | |||
982 | check(typename std::enable_if< | |||
983 | std::is_same<decltype(T::deserialize(std::declval<ChannelT &>(), | |||
984 | std::declval<ConcreteT &>())), | |||
985 | Error>::value, | |||
986 | void *>::type); | |||
987 | ||||
988 | template <typename> static std::false_type check(...); | |||
989 | ||||
990 | public: | |||
991 | static const bool value = decltype(check<S>(0))::value; | |||
992 | }; | |||
993 | ||||
994 | /// Contains primitive utilities for defining, calling and handling calls to | |||
995 | /// remote procedures. ChannelT is a bidirectional stream conforming to the | |||
996 | /// RPCChannel interface (see RPCChannel.h), FunctionIdT is a procedure | |||
997 | /// identifier type that must be serializable on ChannelT, and SequenceNumberT | |||
998 | /// is an integral type that will be used to number in-flight function calls. | |||
999 | /// | |||
1000 | /// These utilities support the construction of very primitive RPC utilities. | |||
1001 | /// Their intent is to ensure correct serialization and deserialization of | |||
1002 | /// procedure arguments, and to keep the client and server's view of the API in | |||
1003 | /// sync. | |||
1004 | template <typename ImplT, typename ChannelT, typename FunctionIdT, | |||
1005 | typename SequenceNumberT> | |||
1006 | class RPCEndpointBase { | |||
1007 | protected: | |||
1008 | class OrcRPCInvalid : public Function<OrcRPCInvalid, void()> { | |||
1009 | public: | |||
1010 | static const char *getName() { return "__orc_rpc$invalid"; } | |||
1011 | }; | |||
1012 | ||||
1013 | class OrcRPCResponse : public Function<OrcRPCResponse, void()> { | |||
1014 | public: | |||
1015 | static const char *getName() { return "__orc_rpc$response"; } | |||
1016 | }; | |||
1017 | ||||
1018 | class OrcRPCNegotiate | |||
1019 | : public Function<OrcRPCNegotiate, FunctionIdT(std::string)> { | |||
1020 | public: | |||
1021 | static const char *getName() { return "__orc_rpc$negotiate"; } | |||
1022 | }; | |||
1023 | ||||
1024 | // Helper predicate for testing for the presence of SerializeTraits | |||
1025 | // serializers. | |||
1026 | template <typename WireT, typename ConcreteT> | |||
1027 | class CanSerializeCheck : detail::CanSerialize<ChannelT, WireT, ConcreteT> { | |||
1028 | public: | |||
1029 | using detail::CanSerialize<ChannelT, WireT, ConcreteT>::value; | |||
1030 | ||||
1031 | static_assert(value, "Missing serializer for argument (Can't serialize the " | |||
1032 | "first template type argument of CanSerializeCheck " | |||
1033 | "from the second)"); | |||
1034 | }; | |||
1035 | ||||
1036 | // Helper predicate for testing for the presence of SerializeTraits | |||
1037 | // deserializers. | |||
1038 | template <typename WireT, typename ConcreteT> | |||
1039 | class CanDeserializeCheck | |||
1040 | : detail::CanDeserialize<ChannelT, WireT, ConcreteT> { | |||
1041 | public: | |||
1042 | using detail::CanDeserialize<ChannelT, WireT, ConcreteT>::value; | |||
1043 | ||||
1044 | static_assert(value, "Missing deserializer for argument (Can't deserialize " | |||
1045 | "the second template type argument of " | |||
1046 | "CanDeserializeCheck from the first)"); | |||
1047 | }; | |||
1048 | ||||
1049 | public: | |||
1050 | /// Construct an RPC instance on a channel. | |||
1051 | RPCEndpointBase(ChannelT &C, bool LazyAutoNegotiation) | |||
1052 | : C(C), LazyAutoNegotiation(LazyAutoNegotiation) { | |||
1053 | // Hold ResponseId in a special variable, since we expect Response to be | |||
1054 | // called relatively frequently, and want to avoid the map lookup. | |||
1055 | ResponseId = FnIdAllocator.getResponseId(); | |||
1056 | RemoteFunctionIds[OrcRPCResponse::getPrototype()] = ResponseId; | |||
1057 | ||||
1058 | // Register the negotiate function id and handler. | |||
1059 | auto NegotiateId = FnIdAllocator.getNegotiateId(); | |||
1060 | RemoteFunctionIds[OrcRPCNegotiate::getPrototype()] = NegotiateId; | |||
1061 | Handlers[NegotiateId] = wrapHandler<OrcRPCNegotiate>( | |||
1062 | [this](const std::string &Name) { return handleNegotiate(Name); }); | |||
1063 | } | |||
1064 | ||||
1065 | ||||
1066 | /// Negotiate a function id for Func with the other end of the channel. | |||
1067 | template <typename Func> Error negotiateFunction(bool Retry = false) { | |||
1068 | return getRemoteFunctionId<Func>(true, Retry).takeError(); | |||
1069 | } | |||
1070 | ||||
1071 | /// Append a call Func, does not call send on the channel. | |||
1072 | /// The first argument specifies a user-defined handler to be run when the | |||
1073 | /// function returns. The handler should take an Expected<Func::ReturnType>, | |||
1074 | /// or an Error (if Func::ReturnType is void). The handler will be called | |||
1075 | /// with an error if the return value is abandoned due to a channel error. | |||
1076 | template <typename Func, typename HandlerT, typename... ArgTs> | |||
1077 | Error appendCallAsync(HandlerT Handler, const ArgTs &... Args) { | |||
1078 | ||||
1079 | static_assert( | |||
1080 | detail::RPCArgTypeCheck<CanSerializeCheck, typename Func::Type, | |||
1081 | void(ArgTs...)>::value, | |||
1082 | ""); | |||
1083 | ||||
1084 | // Look up the function ID. | |||
1085 | FunctionIdT FnId; | |||
1086 | if (auto FnIdOrErr = getRemoteFunctionId<Func>(LazyAutoNegotiation, false)) | |||
1087 | FnId = *FnIdOrErr; | |||
1088 | else { | |||
1089 | // Negotiation failed. Notify the handler then return the negotiate-failed | |||
1090 | // error. | |||
1091 | cantFail(Handler(make_error<ResponseAbandoned>())); | |||
1092 | return FnIdOrErr.takeError(); | |||
1093 | } | |||
1094 | ||||
1095 | SequenceNumberT SeqNo; // initialized in locked scope below. | |||
1096 | { | |||
1097 | // Lock the pending responses map and sequence number manager. | |||
1098 | std::lock_guard<std::mutex> Lock(ResponsesMutex); | |||
1099 | ||||
1100 | // Allocate a sequence number. | |||
1101 | SeqNo = SequenceNumberMgr.getSequenceNumber(); | |||
1102 | assert(!PendingResponses.count(SeqNo) &&(static_cast <bool> (!PendingResponses.count(SeqNo) && "Sequence number already allocated") ? void (0) : __assert_fail ("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1103, __extension__ __PRETTY_FUNCTION__)) | |||
1103 | "Sequence number already allocated")(static_cast <bool> (!PendingResponses.count(SeqNo) && "Sequence number already allocated") ? void (0) : __assert_fail ("!PendingResponses.count(SeqNo) && \"Sequence number already allocated\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1103, __extension__ __PRETTY_FUNCTION__)); | |||
1104 | ||||
1105 | // Install the user handler. | |||
1106 | PendingResponses[SeqNo] = | |||
1107 | detail::createResponseHandler<ChannelT, typename Func::ReturnType>( | |||
1108 | std::move(Handler)); | |||
1109 | } | |||
1110 | ||||
1111 | // Open the function call message. | |||
1112 | if (auto Err = C.startSendMessage(FnId, SeqNo)) { | |||
1113 | abandonPendingResponses(); | |||
1114 | return Err; | |||
1115 | } | |||
1116 | ||||
1117 | // Serialize the call arguments. | |||
1118 | if (auto Err = detail::HandlerTraits<typename Func::Type>::serializeArgs( | |||
1119 | C, Args...)) { | |||
1120 | abandonPendingResponses(); | |||
1121 | return Err; | |||
1122 | } | |||
1123 | ||||
1124 | // Close the function call messagee. | |||
1125 | if (auto Err = C.endSendMessage()) { | |||
1126 | abandonPendingResponses(); | |||
1127 | return Err; | |||
1128 | } | |||
1129 | ||||
1130 | return Error::success(); | |||
1131 | } | |||
1132 | ||||
1133 | Error sendAppendedCalls() { return C.send(); }; | |||
1134 | ||||
1135 | template <typename Func, typename HandlerT, typename... ArgTs> | |||
1136 | Error callAsync(HandlerT Handler, const ArgTs &... Args) { | |||
1137 | if (auto Err = appendCallAsync<Func>(std::move(Handler), Args...)) | |||
1138 | return Err; | |||
1139 | return C.send(); | |||
1140 | } | |||
1141 | ||||
1142 | /// Handle one incoming call. | |||
1143 | Error handleOne() { | |||
1144 | FunctionIdT FnId; | |||
1145 | SequenceNumberT SeqNo; | |||
1146 | if (auto Err = C.startReceiveMessage(FnId, SeqNo)) { | |||
1147 | abandonPendingResponses(); | |||
1148 | return Err; | |||
1149 | } | |||
1150 | if (FnId == ResponseId) | |||
1151 | return handleResponse(SeqNo); | |||
| ||||
1152 | auto I = Handlers.find(FnId); | |||
1153 | if (I != Handlers.end()) | |||
1154 | return I->second(C, SeqNo); | |||
1155 | ||||
1156 | // else: No handler found. Report error to client? | |||
1157 | return make_error<BadFunctionCall<FunctionIdT, SequenceNumberT>>(FnId, | |||
1158 | SeqNo); | |||
1159 | } | |||
1160 | ||||
1161 | /// Helper for handling setter procedures - this method returns a functor that | |||
1162 | /// sets the variables referred to by Args... to values deserialized from the | |||
1163 | /// channel. | |||
1164 | /// E.g. | |||
1165 | /// | |||
1166 | /// typedef Function<0, bool, int> Func1; | |||
1167 | /// | |||
1168 | /// ... | |||
1169 | /// bool B; | |||
1170 | /// int I; | |||
1171 | /// if (auto Err = expect<Func1>(Channel, readArgs(B, I))) | |||
1172 | /// /* Handle Args */ ; | |||
1173 | /// | |||
1174 | template <typename... ArgTs> | |||
1175 | static detail::ReadArgs<ArgTs...> readArgs(ArgTs &... Args) { | |||
1176 | return detail::ReadArgs<ArgTs...>(Args...); | |||
1177 | } | |||
1178 | ||||
1179 | /// Abandon all outstanding result handlers. | |||
1180 | /// | |||
1181 | /// This will call all currently registered result handlers to receive an | |||
1182 | /// "abandoned" error as their argument. This is used internally by the RPC | |||
1183 | /// in error situations, but can also be called directly by clients who are | |||
1184 | /// disconnecting from the remote and don't or can't expect responses to their | |||
1185 | /// outstanding calls. (Especially for outstanding blocking calls, calling | |||
1186 | /// this function may be necessary to avoid dead threads). | |||
1187 | void abandonPendingResponses() { | |||
1188 | // Lock the pending responses map and sequence number manager. | |||
1189 | std::lock_guard<std::mutex> Lock(ResponsesMutex); | |||
1190 | ||||
1191 | for (auto &KV : PendingResponses) | |||
1192 | KV.second->abandon(); | |||
1193 | PendingResponses.clear(); | |||
1194 | SequenceNumberMgr.reset(); | |||
1195 | } | |||
1196 | ||||
1197 | /// Remove the handler for the given function. | |||
1198 | /// A handler must currently be registered for this function. | |||
1199 | template <typename Func> | |||
1200 | void removeHandler() { | |||
1201 | auto IdItr = LocalFunctionIds.find(Func::getPrototype()); | |||
1202 | assert(IdItr != LocalFunctionIds.end() &&(static_cast <bool> (IdItr != LocalFunctionIds.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1203, __extension__ __PRETTY_FUNCTION__)) | |||
1203 | "Function does not have a registered handler")(static_cast <bool> (IdItr != LocalFunctionIds.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("IdItr != LocalFunctionIds.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1203, __extension__ __PRETTY_FUNCTION__)); | |||
1204 | auto HandlerItr = Handlers.find(IdItr->second); | |||
1205 | assert(HandlerItr != Handlers.end() &&(static_cast <bool> (HandlerItr != Handlers.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("HandlerItr != Handlers.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1206, __extension__ __PRETTY_FUNCTION__)) | |||
1206 | "Function does not have a registered handler")(static_cast <bool> (HandlerItr != Handlers.end() && "Function does not have a registered handler") ? void (0) : __assert_fail ("HandlerItr != Handlers.end() && \"Function does not have a registered handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1206, __extension__ __PRETTY_FUNCTION__)); | |||
1207 | Handlers.erase(HandlerItr); | |||
1208 | } | |||
1209 | ||||
1210 | /// Clear all handlers. | |||
1211 | void clearHandlers() { | |||
1212 | Handlers.clear(); | |||
1213 | } | |||
1214 | ||||
1215 | protected: | |||
1216 | ||||
1217 | FunctionIdT getInvalidFunctionId() const { | |||
1218 | return FnIdAllocator.getInvalidId(); | |||
1219 | } | |||
1220 | ||||
1221 | /// Add the given handler to the handler map and make it available for | |||
1222 | /// autonegotiation and execution. | |||
1223 | template <typename Func, typename HandlerT> | |||
1224 | void addHandlerImpl(HandlerT Handler) { | |||
1225 | ||||
1226 | static_assert(detail::RPCArgTypeCheck< | |||
1227 | CanDeserializeCheck, typename Func::Type, | |||
1228 | typename detail::HandlerTraits<HandlerT>::Type>::value, | |||
1229 | ""); | |||
1230 | ||||
1231 | FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>(); | |||
1232 | LocalFunctionIds[Func::getPrototype()] = NewFnId; | |||
1233 | Handlers[NewFnId] = wrapHandler<Func>(std::move(Handler)); | |||
1234 | } | |||
1235 | ||||
1236 | template <typename Func, typename HandlerT> | |||
1237 | void addAsyncHandlerImpl(HandlerT Handler) { | |||
1238 | ||||
1239 | static_assert(detail::RPCArgTypeCheck< | |||
1240 | CanDeserializeCheck, typename Func::Type, | |||
1241 | typename detail::AsyncHandlerTraits< | |||
1242 | typename detail::HandlerTraits<HandlerT>::Type | |||
1243 | >::Type>::value, | |||
1244 | ""); | |||
1245 | ||||
1246 | FunctionIdT NewFnId = FnIdAllocator.template allocate<Func>(); | |||
1247 | LocalFunctionIds[Func::getPrototype()] = NewFnId; | |||
1248 | Handlers[NewFnId] = wrapAsyncHandler<Func>(std::move(Handler)); | |||
1249 | } | |||
1250 | ||||
1251 | Error handleResponse(SequenceNumberT SeqNo) { | |||
1252 | using Handler = typename decltype(PendingResponses)::mapped_type; | |||
1253 | Handler PRHandler; | |||
1254 | ||||
1255 | { | |||
1256 | // Lock the pending responses map and sequence number manager. | |||
1257 | std::unique_lock<std::mutex> Lock(ResponsesMutex); | |||
1258 | auto I = PendingResponses.find(SeqNo); | |||
1259 | ||||
1260 | if (I != PendingResponses.end()) { | |||
1261 | PRHandler = std::move(I->second); | |||
1262 | PendingResponses.erase(I); | |||
1263 | SequenceNumberMgr.releaseSequenceNumber(SeqNo); | |||
1264 | } else { | |||
1265 | // Unlock the pending results map to prevent recursive lock. | |||
1266 | Lock.unlock(); | |||
1267 | abandonPendingResponses(); | |||
1268 | return make_error< | |||
1269 | InvalidSequenceNumberForResponse<SequenceNumberT>>(SeqNo); | |||
1270 | } | |||
1271 | } | |||
1272 | ||||
1273 | assert(PRHandler &&(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out" ) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1274, __extension__ __PRETTY_FUNCTION__)) | |||
1274 | "If we didn't find a response handler we should have bailed out")(static_cast <bool> (PRHandler && "If we didn't find a response handler we should have bailed out" ) ? void (0) : __assert_fail ("PRHandler && \"If we didn't find a response handler we should have bailed out\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCUtils.h" , 1274, __extension__ __PRETTY_FUNCTION__)); | |||
1275 | ||||
1276 | if (auto Err = PRHandler->handleResponse(C)) { | |||
1277 | abandonPendingResponses(); | |||
1278 | return Err; | |||
1279 | } | |||
1280 | ||||
1281 | return Error::success(); | |||
1282 | } | |||
1283 | ||||
1284 | FunctionIdT handleNegotiate(const std::string &Name) { | |||
1285 | auto I = LocalFunctionIds.find(Name); | |||
1286 | if (I == LocalFunctionIds.end()) | |||
1287 | return getInvalidFunctionId(); | |||
1288 | return I->second; | |||
1289 | } | |||
1290 | ||||
1291 | // Find the remote FunctionId for the given function. | |||
1292 | template <typename Func> | |||
1293 | Expected<FunctionIdT> getRemoteFunctionId(bool NegotiateIfNotInMap, | |||
1294 | bool NegotiateIfInvalid) { | |||
1295 | bool DoNegotiate; | |||
1296 | ||||
1297 | // Check if we already have a function id... | |||
1298 | auto I = RemoteFunctionIds.find(Func::getPrototype()); | |||
1299 | if (I != RemoteFunctionIds.end()) { | |||
1300 | // If it's valid there's nothing left to do. | |||
1301 | if (I->second != getInvalidFunctionId()) | |||
1302 | return I->second; | |||
1303 | DoNegotiate = NegotiateIfInvalid; | |||
1304 | } else | |||
1305 | DoNegotiate = NegotiateIfNotInMap; | |||
1306 | ||||
1307 | // We don't have a function id for Func yet, but we're allowed to try to | |||
1308 | // negotiate one. | |||
1309 | if (DoNegotiate) { | |||
1310 | auto &Impl = static_cast<ImplT &>(*this); | |||
1311 | if (auto RemoteIdOrErr = | |||
1312 | Impl.template callB<OrcRPCNegotiate>(Func::getPrototype())) { | |||
1313 | RemoteFunctionIds[Func::getPrototype()] = *RemoteIdOrErr; | |||
1314 | if (*RemoteIdOrErr == getInvalidFunctionId()) | |||
1315 | return make_error<CouldNotNegotiate>(Func::getPrototype()); | |||
1316 | return *RemoteIdOrErr; | |||
1317 | } else | |||
1318 | return RemoteIdOrErr.takeError(); | |||
1319 | } | |||
1320 | ||||
1321 | // No key was available in the map and we weren't allowed to try to | |||
1322 | // negotiate one, so return an unknown function error. | |||
1323 | return make_error<CouldNotNegotiate>(Func::getPrototype()); | |||
1324 | } | |||
1325 | ||||
1326 | using WrappedHandlerFn = std::function<Error(ChannelT &, SequenceNumberT)>; | |||
1327 | ||||
1328 | // Wrap the given user handler in the necessary argument-deserialization code, | |||
1329 | // result-serialization code, and call to the launch policy (if present). | |||
1330 | template <typename Func, typename HandlerT> | |||
1331 | WrappedHandlerFn wrapHandler(HandlerT Handler) { | |||
1332 | return [this, Handler](ChannelT &Channel, | |||
1333 | SequenceNumberT SeqNo) mutable -> Error { | |||
1334 | // Start by deserializing the arguments. | |||
1335 | using ArgsTuple = | |||
1336 | typename detail::FunctionArgsTuple< | |||
1337 | typename detail::HandlerTraits<HandlerT>::Type>::Type; | |||
1338 | auto Args = std::make_shared<ArgsTuple>(); | |||
1339 | ||||
1340 | if (auto Err = | |||
1341 | detail::HandlerTraits<typename Func::Type>::deserializeArgs( | |||
1342 | Channel, *Args)) | |||
1343 | return Err; | |||
1344 | ||||
1345 | // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning | |||
1346 | // for RPCArgs. Void cast RPCArgs to work around this for now. | |||
1347 | // FIXME: Remove this workaround once we can assume a working GCC version. | |||
1348 | (void)Args; | |||
1349 | ||||
1350 | // End receieve message, unlocking the channel for reading. | |||
1351 | if (auto Err = Channel.endReceiveMessage()) | |||
1352 | return Err; | |||
1353 | ||||
1354 | using HTraits = detail::HandlerTraits<HandlerT>; | |||
1355 | using FuncReturn = typename Func::ReturnType; | |||
1356 | return detail::respond<FuncReturn>(Channel, ResponseId, SeqNo, | |||
1357 | HTraits::unpackAndRun(Handler, *Args)); | |||
1358 | }; | |||
1359 | } | |||
1360 | ||||
1361 | // Wrap the given user handler in the necessary argument-deserialization code, | |||
1362 | // result-serialization code, and call to the launch policy (if present). | |||
1363 | template <typename Func, typename HandlerT> | |||
1364 | WrappedHandlerFn wrapAsyncHandler(HandlerT Handler) { | |||
1365 | return [this, Handler](ChannelT &Channel, | |||
1366 | SequenceNumberT SeqNo) mutable -> Error { | |||
1367 | // Start by deserializing the arguments. | |||
1368 | using AHTraits = detail::AsyncHandlerTraits< | |||
1369 | typename detail::HandlerTraits<HandlerT>::Type>; | |||
1370 | using ArgsTuple = | |||
1371 | typename detail::FunctionArgsTuple<typename AHTraits::Type>::Type; | |||
1372 | auto Args = std::make_shared<ArgsTuple>(); | |||
1373 | ||||
1374 | if (auto Err = | |||
1375 | detail::HandlerTraits<typename Func::Type>::deserializeArgs( | |||
1376 | Channel, *Args)) | |||
1377 | return Err; | |||
1378 | ||||
1379 | // GCC 4.7 and 4.8 incorrectly issue a -Wunused-but-set-variable warning | |||
1380 | // for RPCArgs. Void cast RPCArgs to work around this for now. | |||
1381 | // FIXME: Remove this workaround once we can assume a working GCC version. | |||
1382 | (void)Args; | |||
1383 | ||||
1384 | // End receieve message, unlocking the channel for reading. | |||
1385 | if (auto Err = Channel.endReceiveMessage()) | |||
1386 | return Err; | |||
1387 | ||||
1388 | using HTraits = detail::HandlerTraits<HandlerT>; | |||
1389 | using FuncReturn = typename Func::ReturnType; | |||
1390 | auto Responder = | |||
1391 | [this, SeqNo](typename AHTraits::ResultType RetVal) -> Error { | |||
1392 | return detail::respond<FuncReturn>(C, ResponseId, SeqNo, | |||
1393 | std::move(RetVal)); | |||
1394 | }; | |||
1395 | ||||
1396 | return HTraits::unpackAndRunAsync(Handler, Responder, *Args); | |||
1397 | }; | |||
1398 | } | |||
1399 | ||||
1400 | ChannelT &C; | |||
1401 | ||||
1402 | bool LazyAutoNegotiation; | |||
1403 | ||||
1404 | RPCFunctionIdAllocator<FunctionIdT> FnIdAllocator; | |||
1405 | ||||
1406 | FunctionIdT ResponseId; | |||
1407 | std::map<std::string, FunctionIdT> LocalFunctionIds; | |||
1408 | std::map<const char *, FunctionIdT> RemoteFunctionIds; | |||
1409 | ||||
1410 | std::map<FunctionIdT, WrappedHandlerFn> Handlers; | |||
1411 | ||||
1412 | std::mutex ResponsesMutex; | |||
1413 | detail::SequenceNumberManager<SequenceNumberT> SequenceNumberMgr; | |||
1414 | std::map<SequenceNumberT, std::unique_ptr<detail::ResponseHandler<ChannelT>>> | |||
1415 | PendingResponses; | |||
1416 | }; | |||
1417 | ||||
1418 | } // end namespace detail | |||
1419 | ||||
1420 | template <typename ChannelT, typename FunctionIdT = uint32_t, | |||
1421 | typename SequenceNumberT = uint32_t> | |||
1422 | class MultiThreadedRPCEndpoint | |||
1423 | : public detail::RPCEndpointBase< | |||
1424 | MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, | |||
1425 | ChannelT, FunctionIdT, SequenceNumberT> { | |||
1426 | private: | |||
1427 | using BaseClass = | |||
1428 | detail::RPCEndpointBase< | |||
1429 | MultiThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, | |||
1430 | ChannelT, FunctionIdT, SequenceNumberT>; | |||
1431 | ||||
1432 | public: | |||
1433 | MultiThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) | |||
1434 | : BaseClass(C, LazyAutoNegotiation) {} | |||
1435 | ||||
1436 | /// Add a handler for the given RPC function. | |||
1437 | /// This installs the given handler functor for the given RPC Function, and | |||
1438 | /// makes the RPC function available for negotiation/calling from the remote. | |||
1439 | template <typename Func, typename HandlerT> | |||
1440 | void addHandler(HandlerT Handler) { | |||
1441 | return this->template addHandlerImpl<Func>(std::move(Handler)); | |||
1442 | } | |||
1443 | ||||
1444 | /// Add a class-method as a handler. | |||
1445 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> | |||
1446 | void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { | |||
1447 | addHandler<Func>( | |||
1448 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); | |||
1449 | } | |||
1450 | ||||
1451 | template <typename Func, typename HandlerT> | |||
1452 | void addAsyncHandler(HandlerT Handler) { | |||
1453 | return this->template addAsyncHandlerImpl<Func>(std::move(Handler)); | |||
1454 | } | |||
1455 | ||||
1456 | /// Add a class-method as a handler. | |||
1457 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> | |||
1458 | void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { | |||
1459 | addAsyncHandler<Func>( | |||
1460 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); | |||
1461 | } | |||
1462 | ||||
1463 | /// Return type for non-blocking call primitives. | |||
1464 | template <typename Func> | |||
1465 | using NonBlockingCallResult = typename detail::ResultTraits< | |||
1466 | typename Func::ReturnType>::ReturnFutureType; | |||
1467 | ||||
1468 | /// Call Func on Channel C. Does not block, does not call send. Returns a pair | |||
1469 | /// of a future result and the sequence number assigned to the result. | |||
1470 | /// | |||
1471 | /// This utility function is primarily used for single-threaded mode support, | |||
1472 | /// where the sequence number can be used to wait for the corresponding | |||
1473 | /// result. In multi-threaded mode the appendCallNB method, which does not | |||
1474 | /// return the sequence numeber, should be preferred. | |||
1475 | template <typename Func, typename... ArgTs> | |||
1476 | Expected<NonBlockingCallResult<Func>> appendCallNB(const ArgTs &... Args) { | |||
1477 | using RTraits = detail::ResultTraits<typename Func::ReturnType>; | |||
1478 | using ErrorReturn = typename RTraits::ErrorReturnType; | |||
1479 | using ErrorReturnPromise = typename RTraits::ReturnPromiseType; | |||
1480 | ||||
1481 | // FIXME: Stack allocate and move this into the handler once LLVM builds | |||
1482 | // with C++14. | |||
1483 | auto Promise = std::make_shared<ErrorReturnPromise>(); | |||
1484 | auto FutureResult = Promise->get_future(); | |||
1485 | ||||
1486 | if (auto Err = this->template appendCallAsync<Func>( | |||
1487 | [Promise](ErrorReturn RetOrErr) { | |||
1488 | Promise->set_value(std::move(RetOrErr)); | |||
1489 | return Error::success(); | |||
1490 | }, | |||
1491 | Args...)) { | |||
1492 | RTraits::consumeAbandoned(FutureResult.get()); | |||
1493 | return std::move(Err); | |||
1494 | } | |||
1495 | return std::move(FutureResult); | |||
1496 | } | |||
1497 | ||||
1498 | /// The same as appendCallNBWithSeq, except that it calls C.send() to | |||
1499 | /// flush the channel after serializing the call. | |||
1500 | template <typename Func, typename... ArgTs> | |||
1501 | Expected<NonBlockingCallResult<Func>> callNB(const ArgTs &... Args) { | |||
1502 | auto Result = appendCallNB<Func>(Args...); | |||
1503 | if (!Result) | |||
1504 | return Result; | |||
1505 | if (auto Err = this->C.send()) { | |||
1506 | this->abandonPendingResponses(); | |||
1507 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( | |||
1508 | std::move(Result->get())); | |||
1509 | return std::move(Err); | |||
1510 | } | |||
1511 | return Result; | |||
1512 | } | |||
1513 | ||||
1514 | /// Call Func on Channel C. Blocks waiting for a result. Returns an Error | |||
1515 | /// for void functions or an Expected<T> for functions returning a T. | |||
1516 | /// | |||
1517 | /// This function is for use in threaded code where another thread is | |||
1518 | /// handling responses and incoming calls. | |||
1519 | template <typename Func, typename... ArgTs, | |||
1520 | typename AltRetT = typename Func::ReturnType> | |||
1521 | typename detail::ResultTraits<AltRetT>::ErrorReturnType | |||
1522 | callB(const ArgTs &... Args) { | |||
1523 | if (auto FutureResOrErr = callNB<Func>(Args...)) | |||
1524 | return FutureResOrErr->get(); | |||
1525 | else | |||
1526 | return FutureResOrErr.takeError(); | |||
1527 | } | |||
1528 | ||||
1529 | /// Handle incoming RPC calls. | |||
1530 | Error handlerLoop() { | |||
1531 | while (true) | |||
1532 | if (auto Err = this->handleOne()) | |||
1533 | return Err; | |||
1534 | return Error::success(); | |||
1535 | } | |||
1536 | }; | |||
1537 | ||||
1538 | template <typename ChannelT, typename FunctionIdT = uint32_t, | |||
1539 | typename SequenceNumberT = uint32_t> | |||
1540 | class SingleThreadedRPCEndpoint | |||
1541 | : public detail::RPCEndpointBase< | |||
1542 | SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, | |||
1543 | ChannelT, FunctionIdT, SequenceNumberT> { | |||
1544 | private: | |||
1545 | using BaseClass = | |||
1546 | detail::RPCEndpointBase< | |||
1547 | SingleThreadedRPCEndpoint<ChannelT, FunctionIdT, SequenceNumberT>, | |||
1548 | ChannelT, FunctionIdT, SequenceNumberT>; | |||
1549 | ||||
1550 | public: | |||
1551 | SingleThreadedRPCEndpoint(ChannelT &C, bool LazyAutoNegotiation) | |||
1552 | : BaseClass(C, LazyAutoNegotiation) {} | |||
1553 | ||||
1554 | template <typename Func, typename HandlerT> | |||
1555 | void addHandler(HandlerT Handler) { | |||
1556 | return this->template addHandlerImpl<Func>(std::move(Handler)); | |||
1557 | } | |||
1558 | ||||
1559 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> | |||
1560 | void addHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { | |||
1561 | addHandler<Func>( | |||
1562 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); | |||
1563 | } | |||
1564 | ||||
1565 | template <typename Func, typename HandlerT> | |||
1566 | void addAsyncHandler(HandlerT Handler) { | |||
1567 | return this->template addAsyncHandlerImpl<Func>(std::move(Handler)); | |||
1568 | } | |||
1569 | ||||
1570 | /// Add a class-method as a handler. | |||
1571 | template <typename Func, typename ClassT, typename RetT, typename... ArgTs> | |||
1572 | void addAsyncHandler(ClassT &Object, RetT (ClassT::*Method)(ArgTs...)) { | |||
1573 | addAsyncHandler<Func>( | |||
1574 | detail::MemberFnWrapper<ClassT, RetT, ArgTs...>(Object, Method)); | |||
1575 | } | |||
1576 | ||||
1577 | template <typename Func, typename... ArgTs, | |||
1578 | typename AltRetT = typename Func::ReturnType> | |||
1579 | typename detail::ResultTraits<AltRetT>::ErrorReturnType | |||
1580 | callB(const ArgTs &... Args) { | |||
1581 | bool ReceivedResponse = false; | |||
1582 | using ResultType = typename detail::ResultTraits<AltRetT>::ErrorReturnType; | |||
1583 | auto Result = detail::ResultTraits<AltRetT>::createBlankErrorReturnValue(); | |||
1584 | ||||
1585 | // We have to 'Check' result (which we know is in a success state at this | |||
1586 | // point) so that it can be overwritten in the async handler. | |||
1587 | (void)!!Result; | |||
1588 | ||||
1589 | if (auto Err = this->template appendCallAsync<Func>( | |||
1590 | [&](ResultType R) { | |||
1591 | Result = std::move(R); | |||
1592 | ReceivedResponse = true; | |||
1593 | return Error::success(); | |||
1594 | }, | |||
1595 | Args...)) { | |||
1596 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( | |||
1597 | std::move(Result)); | |||
1598 | return std::move(Err); | |||
1599 | } | |||
1600 | ||||
1601 | while (!ReceivedResponse) { | |||
1602 | if (auto Err = this->handleOne()) { | |||
1603 | detail::ResultTraits<typename Func::ReturnType>::consumeAbandoned( | |||
1604 | std::move(Result)); | |||
1605 | return std::move(Err); | |||
1606 | } | |||
1607 | } | |||
1608 | ||||
1609 | return Result; | |||
1610 | } | |||
1611 | }; | |||
1612 | ||||
1613 | /// Asynchronous dispatch for a function on an RPC endpoint. | |||
1614 | template <typename RPCClass, typename Func> | |||
1615 | class RPCAsyncDispatch { | |||
1616 | public: | |||
1617 | RPCAsyncDispatch(RPCClass &Endpoint) : Endpoint(Endpoint) {} | |||
1618 | ||||
1619 | template <typename HandlerT, typename... ArgTs> | |||
1620 | Error operator()(HandlerT Handler, const ArgTs &... Args) const { | |||
1621 | return Endpoint.template appendCallAsync<Func>(std::move(Handler), Args...); | |||
1622 | } | |||
1623 | ||||
1624 | private: | |||
1625 | RPCClass &Endpoint; | |||
1626 | }; | |||
1627 | ||||
1628 | /// Construct an asynchronous dispatcher from an RPC endpoint and a Func. | |||
1629 | template <typename Func, typename RPCEndpointT> | |||
1630 | RPCAsyncDispatch<RPCEndpointT, Func> rpcAsyncDispatch(RPCEndpointT &Endpoint) { | |||
1631 | return RPCAsyncDispatch<RPCEndpointT, Func>(Endpoint); | |||
1632 | } | |||
1633 | ||||
1634 | /// \brief Allows a set of asynchrounous calls to be dispatched, and then | |||
1635 | /// waited on as a group. | |||
1636 | class ParallelCallGroup { | |||
1637 | public: | |||
1638 | ||||
1639 | ParallelCallGroup() = default; | |||
1640 | ParallelCallGroup(const ParallelCallGroup &) = delete; | |||
1641 | ParallelCallGroup &operator=(const ParallelCallGroup &) = delete; | |||
1642 | ||||
1643 | /// \brief Make as asynchronous call. | |||
1644 | template <typename AsyncDispatcher, typename HandlerT, typename... ArgTs> | |||
1645 | Error call(const AsyncDispatcher &AsyncDispatch, HandlerT Handler, | |||
1646 | const ArgTs &... Args) { | |||
1647 | // Increment the count of outstanding calls. This has to happen before | |||
1648 | // we invoke the call, as the handler may (depending on scheduling) | |||
1649 | // be run immediately on another thread, and we don't want the decrement | |||
1650 | // in the wrapped handler below to run before the increment. | |||
1651 | { | |||
1652 | std::unique_lock<std::mutex> Lock(M); | |||
1653 | ++NumOutstandingCalls; | |||
1654 | } | |||
1655 | ||||
1656 | // Wrap the user handler in a lambda that will decrement the | |||
1657 | // outstanding calls count, then poke the condition variable. | |||
1658 | using ArgType = typename detail::ResponseHandlerArg< | |||
1659 | typename detail::HandlerTraits<HandlerT>::Type>::ArgType; | |||
1660 | // FIXME: Move handler into wrapped handler once we have C++14. | |||
1661 | auto WrappedHandler = [this, Handler](ArgType Arg) { | |||
1662 | auto Err = Handler(std::move(Arg)); | |||
1663 | std::unique_lock<std::mutex> Lock(M); | |||
1664 | --NumOutstandingCalls; | |||
1665 | CV.notify_all(); | |||
1666 | return Err; | |||
1667 | }; | |||
1668 | ||||
1669 | return AsyncDispatch(std::move(WrappedHandler), Args...); | |||
1670 | } | |||
1671 | ||||
1672 | /// \brief Blocks until all calls have been completed and their return value | |||
1673 | /// handlers run. | |||
1674 | void wait() { | |||
1675 | std::unique_lock<std::mutex> Lock(M); | |||
1676 | while (NumOutstandingCalls > 0) | |||
1677 | CV.wait(Lock); | |||
1678 | } | |||
1679 | ||||
1680 | private: | |||
1681 | std::mutex M; | |||
1682 | std::condition_variable CV; | |||
1683 | uint32_t NumOutstandingCalls = 0; | |||
1684 | }; | |||
1685 | ||||
1686 | /// @brief Convenience class for grouping RPC Functions into APIs that can be | |||
1687 | /// negotiated as a block. | |||
1688 | /// | |||
1689 | template <typename... Funcs> | |||
1690 | class APICalls { | |||
1691 | public: | |||
1692 | ||||
1693 | /// @brief Test whether this API contains Function F. | |||
1694 | template <typename F> | |||
1695 | class Contains { | |||
1696 | public: | |||
1697 | static const bool value = false; | |||
1698 | }; | |||
1699 | ||||
1700 | /// @brief Negotiate all functions in this API. | |||
1701 | template <typename RPCEndpoint> | |||
1702 | static Error negotiate(RPCEndpoint &R) { | |||
1703 | return Error::success(); | |||
1704 | } | |||
1705 | }; | |||
1706 | ||||
1707 | template <typename Func, typename... Funcs> | |||
1708 | class APICalls<Func, Funcs...> { | |||
1709 | public: | |||
1710 | ||||
1711 | template <typename F> | |||
1712 | class Contains { | |||
1713 | public: | |||
1714 | static const bool value = std::is_same<F, Func>::value | | |||
1715 | APICalls<Funcs...>::template Contains<F>::value; | |||
1716 | }; | |||
1717 | ||||
1718 | template <typename RPCEndpoint> | |||
1719 | static Error negotiate(RPCEndpoint &R) { | |||
1720 | if (auto Err = R.template negotiateFunction<Func>()) | |||
1721 | return Err; | |||
1722 | return APICalls<Funcs...>::negotiate(R); | |||
1723 | } | |||
1724 | ||||
1725 | }; | |||
1726 | ||||
1727 | template <typename... InnerFuncs, typename... Funcs> | |||
1728 | class APICalls<APICalls<InnerFuncs...>, Funcs...> { | |||
1729 | public: | |||
1730 | ||||
1731 | template <typename F> | |||
1732 | class Contains { | |||
1733 | public: | |||
1734 | static const bool value = | |||
1735 | APICalls<InnerFuncs...>::template Contains<F>::value | | |||
1736 | APICalls<Funcs...>::template Contains<F>::value; | |||
1737 | }; | |||
1738 | ||||
1739 | template <typename RPCEndpoint> | |||
1740 | static Error negotiate(RPCEndpoint &R) { | |||
1741 | if (auto Err = APICalls<InnerFuncs...>::negotiate(R)) | |||
1742 | return Err; | |||
1743 | return APICalls<Funcs...>::negotiate(R); | |||
1744 | } | |||
1745 | ||||
1746 | }; | |||
1747 | ||||
1748 | } // end namespace rpc | |||
1749 | } // end namespace orc | |||
1750 | } // end namespace llvm | |||
1751 | ||||
1752 | #endif |
1 | //===- llvm/ExecutionEngine/Orc/RawByteChannel.h ----------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H |
11 | #define LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H |
12 | |
13 | #include "llvm/ADT/StringRef.h" |
14 | #include "llvm/ExecutionEngine/Orc/RPCSerialization.h" |
15 | #include "llvm/Support/Endian.h" |
16 | #include "llvm/Support/Error.h" |
17 | #include <cstdint> |
18 | #include <mutex> |
19 | #include <string> |
20 | #include <type_traits> |
21 | |
22 | namespace llvm { |
23 | namespace orc { |
24 | namespace rpc { |
25 | |
26 | /// Interface for byte-streams to be used with RPC. |
27 | class RawByteChannel { |
28 | public: |
29 | virtual ~RawByteChannel() = default; |
30 | |
31 | /// Read Size bytes from the stream into *Dst. |
32 | virtual Error readBytes(char *Dst, unsigned Size) = 0; |
33 | |
34 | /// Read size bytes from *Src and append them to the stream. |
35 | virtual Error appendBytes(const char *Src, unsigned Size) = 0; |
36 | |
37 | /// Flush the stream if possible. |
38 | virtual Error send() = 0; |
39 | |
40 | /// Notify the channel that we're starting a message send. |
41 | /// Locks the channel for writing. |
42 | template <typename FunctionIdT, typename SequenceIdT> |
43 | Error startSendMessage(const FunctionIdT &FnId, const SequenceIdT &SeqNo) { |
44 | writeLock.lock(); |
45 | if (auto Err = serializeSeq(*this, FnId, SeqNo)) { |
46 | writeLock.unlock(); |
47 | return Err; |
48 | } |
49 | return Error::success(); |
50 | } |
51 | |
52 | /// Notify the channel that we're ending a message send. |
53 | /// Unlocks the channel for writing. |
54 | Error endSendMessage() { |
55 | writeLock.unlock(); |
56 | return Error::success(); |
57 | } |
58 | |
59 | /// Notify the channel that we're starting a message receive. |
60 | /// Locks the channel for reading. |
61 | template <typename FunctionIdT, typename SequenceNumberT> |
62 | Error startReceiveMessage(FunctionIdT &FnId, SequenceNumberT &SeqNo) { |
63 | readLock.lock(); |
64 | if (auto Err = deserializeSeq(*this, FnId, SeqNo)) { |
65 | readLock.unlock(); |
66 | return Err; |
67 | } |
68 | return Error::success(); |
69 | } |
70 | |
71 | /// Notify the channel that we're ending a message receive. |
72 | /// Unlocks the channel for reading. |
73 | Error endReceiveMessage() { |
74 | readLock.unlock(); |
75 | return Error::success(); |
76 | } |
77 | |
78 | /// Get the lock for stream reading. |
79 | std::mutex &getReadLock() { return readLock; } |
80 | |
81 | /// Get the lock for stream writing. |
82 | std::mutex &getWriteLock() { return writeLock; } |
83 | |
84 | private: |
85 | std::mutex readLock, writeLock; |
86 | }; |
87 | |
88 | template <typename ChannelT, typename T> |
89 | class SerializationTraits< |
90 | ChannelT, T, T, |
91 | typename std::enable_if< |
92 | std::is_base_of<RawByteChannel, ChannelT>::value && |
93 | (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value || |
94 | std::is_same<T, uint16_t>::value || std::is_same<T, int16_t>::value || |
95 | std::is_same<T, uint32_t>::value || std::is_same<T, int32_t>::value || |
96 | std::is_same<T, uint64_t>::value || std::is_same<T, int64_t>::value || |
97 | std::is_same<T, char>::value)>::type> { |
98 | public: |
99 | static Error serialize(ChannelT &C, T V) { |
100 | support::endian::byte_swap<T, support::big>(V); |
101 | return C.appendBytes(reinterpret_cast<const char *>(&V), sizeof(T)); |
102 | }; |
103 | |
104 | static Error deserialize(ChannelT &C, T &V) { |
105 | if (auto Err = C.readBytes(reinterpret_cast<char *>(&V), sizeof(T))) |
106 | return Err; |
107 | support::endian::byte_swap<T, support::big>(V); |
108 | return Error::success(); |
109 | }; |
110 | }; |
111 | |
112 | template <typename ChannelT> |
113 | class SerializationTraits<ChannelT, bool, bool, |
114 | typename std::enable_if<std::is_base_of< |
115 | RawByteChannel, ChannelT>::value>::type> { |
116 | public: |
117 | static Error serialize(ChannelT &C, bool V) { |
118 | uint8_t Tmp = V ? 1 : 0; |
119 | if (auto Err = |
120 | C.appendBytes(reinterpret_cast<const char *>(&Tmp), 1)) |
121 | return Err; |
122 | return Error::success(); |
123 | } |
124 | |
125 | static Error deserialize(ChannelT &C, bool &V) { |
126 | uint8_t Tmp = 0; |
127 | if (auto Err = C.readBytes(reinterpret_cast<char *>(&Tmp), 1)) |
128 | return Err; |
129 | V = Tmp != 0; |
130 | return Error::success(); |
131 | } |
132 | }; |
133 | |
134 | template <typename ChannelT> |
135 | class SerializationTraits<ChannelT, std::string, StringRef, |
136 | typename std::enable_if<std::is_base_of< |
137 | RawByteChannel, ChannelT>::value>::type> { |
138 | public: |
139 | /// RPC channel serialization for std::strings. |
140 | static Error serialize(RawByteChannel &C, StringRef S) { |
141 | if (auto Err = serializeSeq(C, static_cast<uint64_t>(S.size()))) |
142 | return Err; |
143 | return C.appendBytes((const char *)S.data(), S.size()); |
144 | } |
145 | }; |
146 | |
147 | template <typename ChannelT, typename T> |
148 | class SerializationTraits<ChannelT, std::string, T, |
149 | typename std::enable_if< |
150 | std::is_base_of<RawByteChannel, ChannelT>::value && |
151 | (std::is_same<T, const char*>::value || |
152 | std::is_same<T, char*>::value)>::type> { |
153 | public: |
154 | static Error serialize(RawByteChannel &C, const char *S) { |
155 | return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C, |
156 | S); |
157 | } |
158 | }; |
159 | |
160 | template <typename ChannelT> |
161 | class SerializationTraits<ChannelT, std::string, std::string, |
162 | typename std::enable_if<std::is_base_of< |
163 | RawByteChannel, ChannelT>::value>::type> { |
164 | public: |
165 | /// RPC channel serialization for std::strings. |
166 | static Error serialize(RawByteChannel &C, const std::string &S) { |
167 | return SerializationTraits<ChannelT, std::string, StringRef>::serialize(C, |
168 | S); |
169 | } |
170 | |
171 | /// RPC channel deserialization for std::strings. |
172 | static Error deserialize(RawByteChannel &C, std::string &S) { |
173 | uint64_t Count = 0; |
174 | if (auto Err = deserializeSeq(C, Count)) |
175 | return Err; |
176 | S.resize(Count); |
177 | return C.readBytes(&S[0], Count); |
178 | } |
179 | }; |
180 | |
181 | } // end namespace rpc |
182 | } // end namespace orc |
183 | } // end namespace llvm |
184 | |
185 | #endif // LLVM_EXECUTIONENGINE_ORC_RAWBYTECHANNEL_H |
1 | // std::mutex implementation -*- C++ -*- |
2 | |
3 | // Copyright (C) 2003-2017 Free Software Foundation, Inc. |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free |
6 | // software; you can redistribute it and/or modify it under the |
7 | // terms of the GNU General Public License as published by the |
8 | // Free Software Foundation; either version 3, or (at your option) |
9 | // any later version. |
10 | |
11 | // This library is distributed in the hope that it will be useful, |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | // GNU General Public License for more details. |
15 | |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version |
18 | // 3.1, as published by the Free Software Foundation. |
19 | |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
23 | // <http://www.gnu.org/licenses/>. |
24 | |
25 | /** @file bits/std_mutex.h |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{mutex} |
28 | */ |
29 | |
30 | #ifndef _GLIBCXX_MUTEX_H1 |
31 | #define _GLIBCXX_MUTEX_H1 1 |
32 | |
33 | #pragma GCC system_header |
34 | |
35 | #if __cplusplus201103L < 201103L |
36 | # include <bits/c++0x_warning.h> |
37 | #else |
38 | |
39 | #include <system_error> |
40 | #include <bits/functexcept.h> |
41 | #include <bits/gthr.h> |
42 | #include <bits/move.h> // for std::swap |
43 | |
44 | #ifdef _GLIBCXX_USE_C99_STDINT_TR11 |
45 | |
46 | namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default"))) |
47 | { |
48 | _GLIBCXX_BEGIN_NAMESPACE_VERSION |
49 | |
50 | /** |
51 | * @defgroup mutexes Mutexes |
52 | * @ingroup concurrency |
53 | * |
54 | * Classes for mutex support. |
55 | * @{ |
56 | */ |
57 | |
58 | #ifdef _GLIBCXX_HAS_GTHREADS1 |
59 | // Common base class for std::mutex and std::timed_mutex |
60 | class __mutex_base |
61 | { |
62 | protected: |
63 | typedef __gthread_mutex_t __native_type; |
64 | |
65 | #ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } |
66 | __native_type _M_mutex = __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
67 | |
68 | constexpr __mutex_base() noexcept = default; |
69 | #else |
70 | __native_type _M_mutex; |
71 | |
72 | __mutex_base() noexcept |
73 | { |
74 | // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) |
75 | __GTHREAD_MUTEX_INIT_FUNCTION__gthread_mutex_init_function(&_M_mutex); |
76 | } |
77 | |
78 | ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } |
79 | #endif |
80 | |
81 | __mutex_base(const __mutex_base&) = delete; |
82 | __mutex_base& operator=(const __mutex_base&) = delete; |
83 | }; |
84 | |
85 | /// The standard mutex type. |
86 | class mutex : private __mutex_base |
87 | { |
88 | public: |
89 | typedef __native_type* native_handle_type; |
90 | |
91 | #ifdef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } |
92 | constexpr |
93 | #endif |
94 | mutex() noexcept = default; |
95 | ~mutex() = default; |
96 | |
97 | mutex(const mutex&) = delete; |
98 | mutex& operator=(const mutex&) = delete; |
99 | |
100 | void |
101 | lock() |
102 | { |
103 | int __e = __gthread_mutex_lock(&_M_mutex); |
104 | |
105 | // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) |
106 | if (__e) |
107 | __throw_system_error(__e); |
108 | } |
109 | |
110 | bool |
111 | try_lock() noexcept |
112 | { |
113 | // XXX EINVAL, EAGAIN, EBUSY |
114 | return !__gthread_mutex_trylock(&_M_mutex); |
115 | } |
116 | |
117 | void |
118 | unlock() |
119 | { |
120 | // XXX EINVAL, EAGAIN, EPERM |
121 | __gthread_mutex_unlock(&_M_mutex); |
122 | } |
123 | |
124 | native_handle_type |
125 | native_handle() noexcept |
126 | { return &_M_mutex; } |
127 | }; |
128 | |
129 | #endif // _GLIBCXX_HAS_GTHREADS |
130 | |
131 | /// Do not acquire ownership of the mutex. |
132 | struct defer_lock_t { explicit defer_lock_t() = default; }; |
133 | |
134 | /// Try to acquire ownership of the mutex without blocking. |
135 | struct try_to_lock_t { explicit try_to_lock_t() = default; }; |
136 | |
137 | /// Assume the calling thread has already obtained mutex ownership |
138 | /// and manage it. |
139 | struct adopt_lock_t { explicit adopt_lock_t() = default; }; |
140 | |
141 | /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. |
142 | _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; |
143 | |
144 | /// Tag used to prevent a scoped lock from blocking if a mutex is locked. |
145 | _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; |
146 | |
147 | /// Tag used to make a scoped lock take ownership of a locked mutex. |
148 | _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; |
149 | |
150 | /** @brief A simple scoped lock type. |
151 | * |
152 | * A lock_guard controls mutex ownership within a scope, releasing |
153 | * ownership in the destructor. |
154 | */ |
155 | template<typename _Mutex> |
156 | class lock_guard |
157 | { |
158 | public: |
159 | typedef _Mutex mutex_type; |
160 | |
161 | explicit lock_guard(mutex_type& __m) : _M_device(__m) |
162 | { _M_device.lock(); } |
163 | |
164 | lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) |
165 | { } // calling thread owns mutex |
166 | |
167 | ~lock_guard() |
168 | { _M_device.unlock(); } |
169 | |
170 | lock_guard(const lock_guard&) = delete; |
171 | lock_guard& operator=(const lock_guard&) = delete; |
172 | |
173 | private: |
174 | mutex_type& _M_device; |
175 | }; |
176 | |
177 | /** @brief A movable scoped lock type. |
178 | * |
179 | * A unique_lock controls mutex ownership within a scope. Ownership of the |
180 | * mutex can be delayed until after construction and can be transferred |
181 | * to another unique_lock by move construction or move assignment. If a |
182 | * mutex lock is owned when the destructor runs ownership will be released. |
183 | */ |
184 | template<typename _Mutex> |
185 | class unique_lock |
186 | { |
187 | public: |
188 | typedef _Mutex mutex_type; |
189 | |
190 | unique_lock() noexcept |
191 | : _M_device(0), _M_owns(false) |
192 | { } |
193 | |
194 | explicit unique_lock(mutex_type& __m) |
195 | : _M_device(std::__addressof(__m)), _M_owns(false) |
196 | { |
197 | lock(); |
198 | _M_owns = true; |
199 | } |
200 | |
201 | unique_lock(mutex_type& __m, defer_lock_t) noexcept |
202 | : _M_device(std::__addressof(__m)), _M_owns(false) |
203 | { } |
204 | |
205 | unique_lock(mutex_type& __m, try_to_lock_t) |
206 | : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) |
207 | { } |
208 | |
209 | unique_lock(mutex_type& __m, adopt_lock_t) noexcept |
210 | : _M_device(std::__addressof(__m)), _M_owns(true) |
211 | { |
212 | // XXX calling thread owns mutex |
213 | } |
214 | |
215 | template<typename _Clock, typename _Duration> |
216 | unique_lock(mutex_type& __m, |
217 | const chrono::time_point<_Clock, _Duration>& __atime) |
218 | : _M_device(std::__addressof(__m)), |
219 | _M_owns(_M_device->try_lock_until(__atime)) |
220 | { } |
221 | |
222 | template<typename _Rep, typename _Period> |
223 | unique_lock(mutex_type& __m, |
224 | const chrono::duration<_Rep, _Period>& __rtime) |
225 | : _M_device(std::__addressof(__m)), |
226 | _M_owns(_M_device->try_lock_for(__rtime)) |
227 | { } |
228 | |
229 | ~unique_lock() |
230 | { |
231 | if (_M_owns) |
232 | unlock(); |
233 | } |
234 | |
235 | unique_lock(const unique_lock&) = delete; |
236 | unique_lock& operator=(const unique_lock&) = delete; |
237 | |
238 | unique_lock(unique_lock&& __u) noexcept |
239 | : _M_device(__u._M_device), _M_owns(__u._M_owns) |
240 | { |
241 | __u._M_device = 0; |
242 | __u._M_owns = false; |
243 | } |
244 | |
245 | unique_lock& operator=(unique_lock&& __u) noexcept |
246 | { |
247 | if(_M_owns) |
248 | unlock(); |
249 | |
250 | unique_lock(std::move(__u)).swap(*this); |
251 | |
252 | __u._M_device = 0; |
253 | __u._M_owns = false; |
254 | |
255 | return *this; |
256 | } |
257 | |
258 | void |
259 | lock() |
260 | { |
261 | if (!_M_device) |
262 | __throw_system_error(int(errc::operation_not_permitted)); |
263 | else if (_M_owns) |
264 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
265 | else |
266 | { |
267 | _M_device->lock(); |
268 | _M_owns = true; |
269 | } |
270 | } |
271 | |
272 | bool |
273 | try_lock() |
274 | { |
275 | if (!_M_device) |
276 | __throw_system_error(int(errc::operation_not_permitted)); |
277 | else if (_M_owns) |
278 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
279 | else |
280 | { |
281 | _M_owns = _M_device->try_lock(); |
282 | return _M_owns; |
283 | } |
284 | } |
285 | |
286 | template<typename _Clock, typename _Duration> |
287 | bool |
288 | try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) |
289 | { |
290 | if (!_M_device) |
291 | __throw_system_error(int(errc::operation_not_permitted)); |
292 | else if (_M_owns) |
293 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
294 | else |
295 | { |
296 | _M_owns = _M_device->try_lock_until(__atime); |
297 | return _M_owns; |
298 | } |
299 | } |
300 | |
301 | template<typename _Rep, typename _Period> |
302 | bool |
303 | try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) |
304 | { |
305 | if (!_M_device) |
306 | __throw_system_error(int(errc::operation_not_permitted)); |
307 | else if (_M_owns) |
308 | __throw_system_error(int(errc::resource_deadlock_would_occur)); |
309 | else |
310 | { |
311 | _M_owns = _M_device->try_lock_for(__rtime); |
312 | return _M_owns; |
313 | } |
314 | } |
315 | |
316 | void |
317 | unlock() |
318 | { |
319 | if (!_M_owns) |
320 | __throw_system_error(int(errc::operation_not_permitted)); |
321 | else if (_M_device) |
322 | { |
323 | _M_device->unlock(); |
324 | _M_owns = false; |
325 | } |
326 | } |
327 | |
328 | void |
329 | swap(unique_lock& __u) noexcept |
330 | { |
331 | std::swap(_M_device, __u._M_device); |
332 | std::swap(_M_owns, __u._M_owns); |
333 | } |
334 | |
335 | mutex_type* |
336 | release() noexcept |
337 | { |
338 | mutex_type* __ret = _M_device; |
339 | _M_device = 0; |
340 | _M_owns = false; |
341 | return __ret; |
342 | } |
343 | |
344 | bool |
345 | owns_lock() const noexcept |
346 | { return _M_owns; } |
347 | |
348 | explicit operator bool() const noexcept |
349 | { return owns_lock(); } |
350 | |
351 | mutex_type* |
352 | mutex() const noexcept |
353 | { return _M_device; } |
354 | |
355 | private: |
356 | mutex_type* _M_device; |
357 | bool _M_owns; // XXX use atomic_bool |
358 | }; |
359 | |
360 | /// Swap overload for unique_lock objects. |
361 | template<typename _Mutex> |
362 | inline void |
363 | swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept |
364 | { __x.swap(__y); } |
365 | |
366 | // @} group mutexes |
367 | _GLIBCXX_END_NAMESPACE_VERSION |
368 | } // namespace |
369 | #endif // _GLIBCXX_USE_C99_STDINT_TR1 |
370 | |
371 | #endif // C++11 |
372 | |
373 | #endif // _GLIBCXX_MUTEX_H |
1 | /* Threads compatibility routines for libgcc2 and libobjc. */ |
2 | /* Compile this one with gcc. */ |
3 | /* Copyright (C) 1997-2017 Free Software Foundation, Inc. |
4 | |
5 | This file is part of GCC. |
6 | |
7 | GCC is free software; you can redistribute it and/or modify it under |
8 | the terms of the GNU General Public License as published by the Free |
9 | Software Foundation; either version 3, or (at your option) any later |
10 | version. |
11 | |
12 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | for more details. |
16 | |
17 | Under Section 7 of GPL version 3, you are granted additional |
18 | permissions described in the GCC Runtime Library Exception, version |
19 | 3.1, as published by the Free Software Foundation. |
20 | |
21 | You should have received a copy of the GNU General Public License and |
22 | a copy of the GCC Runtime Library Exception along with this program; |
23 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
24 | <http://www.gnu.org/licenses/>. */ |
25 | |
26 | #ifndef _GLIBCXX_GCC_GTHR_POSIX_H |
27 | #define _GLIBCXX_GCC_GTHR_POSIX_H |
28 | |
29 | /* POSIX threads specific definitions. |
30 | Easy, since the interface is just one-to-one mapping. */ |
31 | |
32 | #define __GTHREADS1 1 |
33 | #define __GTHREADS_CXX0X1 1 |
34 | |
35 | #include <pthread.h> |
36 | |
37 | #if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \ |
38 | || !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK1)) |
39 | # include <unistd.h> |
40 | # if defined(_POSIX_TIMEOUTS200809L) && _POSIX_TIMEOUTS200809L >= 0 |
41 | # define _GTHREAD_USE_MUTEX_TIMEDLOCK1 1 |
42 | # else |
43 | # define _GTHREAD_USE_MUTEX_TIMEDLOCK1 0 |
44 | # endif |
45 | #endif |
46 | |
47 | typedef pthread_t __gthread_t; |
48 | typedef pthread_key_t __gthread_key_t; |
49 | typedef pthread_once_t __gthread_once_t; |
50 | typedef pthread_mutex_t __gthread_mutex_t; |
51 | typedef pthread_mutex_t __gthread_recursive_mutex_t; |
52 | typedef pthread_cond_t __gthread_cond_t; |
53 | typedef struct timespec __gthread_time_t; |
54 | |
55 | /* POSIX like conditional variables are supported. Please look at comments |
56 | in gthr.h for details. */ |
57 | #define __GTHREAD_HAS_COND1 1 |
58 | |
59 | #define __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } |
60 | #define __GTHREAD_MUTEX_INIT_FUNCTION__gthread_mutex_init_function __gthread_mutex_init_function |
61 | #define __GTHREAD_ONCE_INIT0 PTHREAD_ONCE_INIT0 |
62 | #if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) |
63 | #define __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } PTHREAD_RECURSIVE_MUTEX_INITIALIZER |
64 | #elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } }) |
65 | #define __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } |
66 | #else |
67 | #define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
68 | #endif |
69 | #define __GTHREAD_COND_INIT{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } PTHREAD_COND_INITIALIZER{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } |
70 | #define __GTHREAD_TIME_INIT{0,0} {0,0} |
71 | |
72 | #ifdef _GTHREAD_USE_MUTEX_INIT_FUNC |
73 | # undef __GTHREAD_MUTEX_INIT{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } } |
74 | #endif |
75 | #ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC |
76 | # undef __GTHREAD_RECURSIVE_MUTEX_INIT{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } } |
77 | # undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION |
78 | # define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
79 | #endif |
80 | #ifdef _GTHREAD_USE_COND_INIT_FUNC |
81 | # undef __GTHREAD_COND_INIT{ { {0}, {0}, {0, 0}, {0, 0}, 0, 0, {0, 0} } } |
82 | # define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function |
83 | #endif |
84 | |
85 | #if __GXX_WEAK__1 && _GLIBCXX_GTHREAD_USE_WEAK1 |
86 | # ifndef __gthrw_pragma |
87 | # define __gthrw_pragma(pragma) |
88 | # endif |
89 | # define __gthrw2(name,name2,type)static __typeof(type) name __attribute__ ((__weakref__("name2" ))); \ |
90 | static __typeof(type) name __attribute__ ((__weakref__(#name2))); \ |
91 | __gthrw_pragma(weak type) |
92 | # define __gthrw_(name)__gthrw_name __gthrw_ ## name |
93 | #else |
94 | # define __gthrw2(name,name2,type)static __typeof(type) name __attribute__ ((__weakref__("name2" ))); |
95 | # define __gthrw_(name)__gthrw_name name |
96 | #endif |
97 | |
98 | /* Typically, __gthrw_foo is a weak reference to symbol foo. */ |
99 | #define __gthrw(name)static __typeof(name) __gthrw_name __attribute__ ((__weakref__ ("name"))); __gthrw2(__gthrw_ ## name,name,name)static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__ ("name"))); |
100 | |
101 | __gthrw(pthread_once)static __typeof(pthread_once) __gthrw_pthread_once __attribute__ ((__weakref__("pthread_once"))); |
102 | __gthrw(pthread_getspecific)static __typeof(pthread_getspecific) __gthrw_pthread_getspecific __attribute__ ((__weakref__("pthread_getspecific"))); |
103 | __gthrw(pthread_setspecific)static __typeof(pthread_setspecific) __gthrw_pthread_setspecific __attribute__ ((__weakref__("pthread_setspecific"))); |
104 | |
105 | __gthrw(pthread_create)static __typeof(pthread_create) __gthrw_pthread_create __attribute__ ((__weakref__("pthread_create"))); |
106 | __gthrw(pthread_join)static __typeof(pthread_join) __gthrw_pthread_join __attribute__ ((__weakref__("pthread_join"))); |
107 | __gthrw(pthread_equal)static __typeof(pthread_equal) __gthrw_pthread_equal __attribute__ ((__weakref__("pthread_equal"))); |
108 | __gthrw(pthread_self)static __typeof(pthread_self) __gthrw_pthread_self __attribute__ ((__weakref__("pthread_self"))); |
109 | __gthrw(pthread_detach)static __typeof(pthread_detach) __gthrw_pthread_detach __attribute__ ((__weakref__("pthread_detach"))); |
110 | #ifndef __BIONIC__ |
111 | __gthrw(pthread_cancel)static __typeof(pthread_cancel) __gthrw_pthread_cancel __attribute__ ((__weakref__("pthread_cancel"))); |
112 | #endif |
113 | __gthrw(sched_yield)static __typeof(sched_yield) __gthrw_sched_yield __attribute__ ((__weakref__("sched_yield"))); |
114 | |
115 | __gthrw(pthread_mutex_lock)static __typeof(pthread_mutex_lock) __gthrw_pthread_mutex_lock __attribute__ ((__weakref__("pthread_mutex_lock"))); |
116 | __gthrw(pthread_mutex_trylock)static __typeof(pthread_mutex_trylock) __gthrw_pthread_mutex_trylock __attribute__ ((__weakref__("pthread_mutex_trylock"))); |
117 | #if _GTHREAD_USE_MUTEX_TIMEDLOCK1 |
118 | __gthrw(pthread_mutex_timedlock)static __typeof(pthread_mutex_timedlock) __gthrw_pthread_mutex_timedlock __attribute__ ((__weakref__("pthread_mutex_timedlock"))); |
119 | #endif |
120 | __gthrw(pthread_mutex_unlock)static __typeof(pthread_mutex_unlock) __gthrw_pthread_mutex_unlock __attribute__ ((__weakref__("pthread_mutex_unlock"))); |
121 | __gthrw(pthread_mutex_init)static __typeof(pthread_mutex_init) __gthrw_pthread_mutex_init __attribute__ ((__weakref__("pthread_mutex_init"))); |
122 | __gthrw(pthread_mutex_destroy)static __typeof(pthread_mutex_destroy) __gthrw_pthread_mutex_destroy __attribute__ ((__weakref__("pthread_mutex_destroy"))); |
123 | |
124 | __gthrw(pthread_cond_init)static __typeof(pthread_cond_init) __gthrw_pthread_cond_init __attribute__ ((__weakref__("pthread_cond_init"))); |
125 | __gthrw(pthread_cond_broadcast)static __typeof(pthread_cond_broadcast) __gthrw_pthread_cond_broadcast __attribute__ ((__weakref__("pthread_cond_broadcast"))); |
126 | __gthrw(pthread_cond_signal)static __typeof(pthread_cond_signal) __gthrw_pthread_cond_signal __attribute__ ((__weakref__("pthread_cond_signal"))); |
127 | __gthrw(pthread_cond_wait)static __typeof(pthread_cond_wait) __gthrw_pthread_cond_wait __attribute__ ((__weakref__("pthread_cond_wait"))); |
128 | __gthrw(pthread_cond_timedwait)static __typeof(pthread_cond_timedwait) __gthrw_pthread_cond_timedwait __attribute__ ((__weakref__("pthread_cond_timedwait"))); |
129 | __gthrw(pthread_cond_destroy)static __typeof(pthread_cond_destroy) __gthrw_pthread_cond_destroy __attribute__ ((__weakref__("pthread_cond_destroy"))); |
130 | |
131 | __gthrw(pthread_key_create)static __typeof(pthread_key_create) __gthrw_pthread_key_create __attribute__ ((__weakref__("pthread_key_create"))); |
132 | __gthrw(pthread_key_delete)static __typeof(pthread_key_delete) __gthrw_pthread_key_delete __attribute__ ((__weakref__("pthread_key_delete"))); |
133 | __gthrw(pthread_mutexattr_init)static __typeof(pthread_mutexattr_init) __gthrw_pthread_mutexattr_init __attribute__ ((__weakref__("pthread_mutexattr_init"))); |
134 | __gthrw(pthread_mutexattr_settype)static __typeof(pthread_mutexattr_settype) __gthrw_pthread_mutexattr_settype __attribute__ ((__weakref__("pthread_mutexattr_settype"))); |
135 | __gthrw(pthread_mutexattr_destroy)static __typeof(pthread_mutexattr_destroy) __gthrw_pthread_mutexattr_destroy __attribute__ ((__weakref__("pthread_mutexattr_destroy"))); |
136 | |
137 | |
138 | #if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) |
139 | /* Objective-C. */ |
140 | __gthrw(pthread_exit)static __typeof(pthread_exit) __gthrw_pthread_exit __attribute__ ((__weakref__("pthread_exit"))); |
141 | #ifdef _POSIX_PRIORITY_SCHEDULING200809L |
142 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L |
143 | __gthrw(sched_get_priority_max)static __typeof(sched_get_priority_max) __gthrw_sched_get_priority_max __attribute__ ((__weakref__("sched_get_priority_max"))); |
144 | __gthrw(sched_get_priority_min)static __typeof(sched_get_priority_min) __gthrw_sched_get_priority_min __attribute__ ((__weakref__("sched_get_priority_min"))); |
145 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
146 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
147 | __gthrw(pthread_attr_destroy)static __typeof(pthread_attr_destroy) __gthrw_pthread_attr_destroy __attribute__ ((__weakref__("pthread_attr_destroy"))); |
148 | __gthrw(pthread_attr_init)static __typeof(pthread_attr_init) __gthrw_pthread_attr_init __attribute__ ((__weakref__("pthread_attr_init"))); |
149 | __gthrw(pthread_attr_setdetachstate)static __typeof(pthread_attr_setdetachstate) __gthrw_pthread_attr_setdetachstate __attribute__ ((__weakref__("pthread_attr_setdetachstate"))) ; |
150 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L |
151 | __gthrw(pthread_getschedparam)static __typeof(pthread_getschedparam) __gthrw_pthread_getschedparam __attribute__ ((__weakref__("pthread_getschedparam"))); |
152 | __gthrw(pthread_setschedparam)static __typeof(pthread_setschedparam) __gthrw_pthread_setschedparam __attribute__ ((__weakref__("pthread_setschedparam"))); |
153 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
154 | #endif /* _LIBOBJC || _LIBOBJC_WEAK */ |
155 | |
156 | #if __GXX_WEAK__1 && _GLIBCXX_GTHREAD_USE_WEAK1 |
157 | |
158 | /* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if |
159 | -pthreads is not specified. The functions are dummies and most return an |
160 | error value. However pthread_once returns 0 without invoking the routine |
161 | it is passed so we cannot pretend that the interface is active if -pthreads |
162 | is not specified. On Solaris 2.5.1, the interface is not exposed at all so |
163 | we need to play the usual game with weak symbols. On Solaris 10 and up, a |
164 | working interface is always exposed. On FreeBSD 6 and later, libc also |
165 | exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up |
166 | to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, |
167 | which means the alternate __gthread_active_p below cannot be used there. */ |
168 | |
169 | #if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) |
170 | |
171 | static volatile int __gthread_active = -1; |
172 | |
173 | static void |
174 | __gthread_trigger (void) |
175 | { |
176 | __gthread_active = 1; |
177 | } |
178 | |
179 | static inline int |
180 | __gthread_active_p (void) |
181 | { |
182 | static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER{ { 0, 0, 0, 0, 0, 0, 0, { 0, 0 } } }; |
183 | static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT0; |
184 | |
185 | /* Avoid reading __gthread_active twice on the main code path. */ |
186 | int __gthread_active_latest_value = __gthread_active; |
187 | |
188 | /* This test is not protected to avoid taking a lock on the main code |
189 | path so every update of __gthread_active in a threaded program must |
190 | be atomic with regard to the result of the test. */ |
191 | if (__builtin_expect (__gthread_active_latest_value < 0, 0)) |
192 | { |
193 | if (__gthrw_(pthread_once)__gthrw_pthread_once) |
194 | { |
195 | /* If this really is a threaded program, then we must ensure that |
196 | __gthread_active has been set to 1 before exiting this block. */ |
197 | __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock (&__gthread_active_mutex); |
198 | __gthrw_(pthread_once)__gthrw_pthread_once (&__gthread_active_once, __gthread_trigger); |
199 | __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock (&__gthread_active_mutex); |
200 | } |
201 | |
202 | /* Make sure we'll never enter this block again. */ |
203 | if (__gthread_active < 0) |
204 | __gthread_active = 0; |
205 | |
206 | __gthread_active_latest_value = __gthread_active; |
207 | } |
208 | |
209 | return __gthread_active_latest_value != 0; |
210 | } |
211 | |
212 | #else /* neither FreeBSD nor Solaris */ |
213 | |
214 | /* For a program to be multi-threaded the only thing that it certainly must |
215 | be using is pthread_create. However, there may be other libraries that |
216 | intercept pthread_create with their own definitions to wrap pthreads |
217 | functionality for some purpose. In those cases, pthread_create being |
218 | defined might not necessarily mean that libpthread is actually linked |
219 | in. |
220 | |
221 | For the GNU C library, we can use a known internal name. This is always |
222 | available in the ABI, but no other library would define it. That is |
223 | ideal, since any public pthread function might be intercepted just as |
224 | pthread_create might be. __pthread_key_create is an "internal" |
225 | implementation symbol, but it is part of the public exported ABI. Also, |
226 | it's among the symbols that the static libpthread.a always links in |
227 | whenever pthread_create is used, so there is no danger of a false |
228 | negative result in any statically-linked, multi-threaded program. |
229 | |
230 | For others, we choose pthread_cancel as a function that seems unlikely |
231 | to be redefined by an interceptor library. The bionic (Android) C |
232 | library does not provide pthread_cancel, so we do use pthread_create |
233 | there (and interceptor libraries lose). */ |
234 | |
235 | #ifdef __GLIBC__2 |
236 | __gthrw2(__gthrw_(__pthread_key_create),static __typeof(pthread_key_create) __gthrw___pthread_key_create __attribute__ ((__weakref__("__pthread_key_create"))); |
237 | __pthread_key_create,static __typeof(pthread_key_create) __gthrw___pthread_key_create __attribute__ ((__weakref__("__pthread_key_create"))); |
238 | pthread_key_create)static __typeof(pthread_key_create) __gthrw___pthread_key_create __attribute__ ((__weakref__("__pthread_key_create"))); |
239 | # define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(__pthread_key_create)__gthrw___pthread_key_create |
240 | #elif defined (__BIONIC__) |
241 | # define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(pthread_create)__gthrw_pthread_create |
242 | #else |
243 | # define GTHR_ACTIVE_PROXY__gthrw___pthread_key_create __gthrw_(pthread_cancel)__gthrw_pthread_cancel |
244 | #endif |
245 | |
246 | static inline int |
247 | __gthread_active_p (void) |
248 | { |
249 | static void *const __gthread_active_ptr |
250 | = __extension__ (void *) >HR_ACTIVE_PROXY__gthrw___pthread_key_create; |
251 | return __gthread_active_ptr != 0; |
252 | } |
253 | |
254 | #endif /* FreeBSD or Solaris */ |
255 | |
256 | #else /* not __GXX_WEAK__ */ |
257 | |
258 | /* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread |
259 | calls in shared flavors of the HP-UX C library. Most of the stubs |
260 | have no functionality. The details are described in the "libc cumulative |
261 | patch" for each subversion of HP-UX 11. There are two special interfaces |
262 | provided for checking whether an application is linked to a shared pthread |
263 | library or not. However, these interfaces aren't available in early |
264 | libpthread libraries. We also need a test that works for archive |
265 | libraries. We can't use pthread_once as some libc versions call the |
266 | init function. We also can't use pthread_create or pthread_attr_init |
267 | as these create a thread and thereby prevent changing the default stack |
268 | size. The function pthread_default_stacksize_np is available in both |
269 | the archive and shared versions of libpthread. It can be used to |
270 | determine the default pthread stack size. There is a stub in some |
271 | shared libc versions which returns a zero size if pthreads are not |
272 | active. We provide an equivalent stub to handle cases where libc |
273 | doesn't provide one. */ |
274 | |
275 | #if defined(__hppa__) && defined(__hpux__) |
276 | |
277 | static volatile int __gthread_active = -1; |
278 | |
279 | static inline int |
280 | __gthread_active_p (void) |
281 | { |
282 | /* Avoid reading __gthread_active twice on the main code path. */ |
283 | int __gthread_active_latest_value = __gthread_active; |
284 | size_t __s; |
285 | |
286 | if (__builtin_expect (__gthread_active_latest_value < 0, 0)) |
287 | { |
288 | pthread_default_stacksize_np (0, &__s); |
289 | __gthread_active = __s ? 1 : 0; |
290 | __gthread_active_latest_value = __gthread_active; |
291 | } |
292 | |
293 | return __gthread_active_latest_value != 0; |
294 | } |
295 | |
296 | #else /* not hppa-hpux */ |
297 | |
298 | static inline int |
299 | __gthread_active_p (void) |
300 | { |
301 | return 1; |
302 | } |
303 | |
304 | #endif /* hppa-hpux */ |
305 | |
306 | #endif /* __GXX_WEAK__ */ |
307 | |
308 | #ifdef _LIBOBJC |
309 | |
310 | /* This is the config.h file in libobjc/ */ |
311 | #include <config.h> |
312 | |
313 | #ifdef HAVE_SCHED_H |
314 | # include <sched.h> |
315 | #endif |
316 | |
317 | /* Key structure for maintaining thread specific storage */ |
318 | static pthread_key_t _objc_thread_storage; |
319 | static pthread_attr_t _objc_thread_attribs; |
320 | |
321 | /* Thread local storage for a single thread */ |
322 | static void *thread_local_storage = NULL__null; |
323 | |
324 | /* Backend initialization functions */ |
325 | |
326 | /* Initialize the threads subsystem. */ |
327 | static inline int |
328 | __gthread_objc_init_thread_system (void) |
329 | { |
330 | if (__gthread_active_p ()) |
331 | { |
332 | /* Initialize the thread storage key. */ |
333 | if (__gthrw_(pthread_key_create)__gthrw_pthread_key_create (&_objc_thread_storage, NULL__null) == 0) |
334 | { |
335 | /* The normal default detach state for threads is |
336 | * PTHREAD_CREATE_JOINABLE which causes threads to not die |
337 | * when you think they should. */ |
338 | if (__gthrw_(pthread_attr_init)__gthrw_pthread_attr_init (&_objc_thread_attribs) == 0 |
339 | && __gthrw_(pthread_attr_setdetachstate)__gthrw_pthread_attr_setdetachstate (&_objc_thread_attribs, |
340 | PTHREAD_CREATE_DETACHEDPTHREAD_CREATE_DETACHED) == 0) |
341 | return 0; |
342 | } |
343 | } |
344 | |
345 | return -1; |
346 | } |
347 | |
348 | /* Close the threads subsystem. */ |
349 | static inline int |
350 | __gthread_objc_close_thread_system (void) |
351 | { |
352 | if (__gthread_active_p () |
353 | && __gthrw_(pthread_key_delete)__gthrw_pthread_key_delete (_objc_thread_storage) == 0 |
354 | && __gthrw_(pthread_attr_destroy)__gthrw_pthread_attr_destroy (&_objc_thread_attribs) == 0) |
355 | return 0; |
356 | |
357 | return -1; |
358 | } |
359 | |
360 | /* Backend thread functions */ |
361 | |
362 | /* Create a new thread of execution. */ |
363 | static inline objc_thread_t |
364 | __gthread_objc_thread_detach (void (*func)(void *), void *arg) |
365 | { |
366 | objc_thread_t thread_id; |
367 | pthread_t new_thread_handle; |
368 | |
369 | if (!__gthread_active_p ()) |
370 | return NULL__null; |
371 | |
372 | if (!(__gthrw_(pthread_create)__gthrw_pthread_create (&new_thread_handle, &_objc_thread_attribs, |
373 | (void *) func, arg))) |
374 | thread_id = (objc_thread_t) new_thread_handle; |
375 | else |
376 | thread_id = NULL__null; |
377 | |
378 | return thread_id; |
379 | } |
380 | |
381 | /* Set the current thread's priority. */ |
382 | static inline int |
383 | __gthread_objc_thread_set_priority (int priority) |
384 | { |
385 | if (!__gthread_active_p ()) |
386 | return -1; |
387 | else |
388 | { |
389 | #ifdef _POSIX_PRIORITY_SCHEDULING200809L |
390 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L |
391 | pthread_t thread_id = __gthrw_(pthread_self)__gthrw_pthread_self (); |
392 | int policy; |
393 | struct sched_param params; |
394 | int priority_min, priority_max; |
395 | |
396 | if (__gthrw_(pthread_getschedparam)__gthrw_pthread_getschedparam (thread_id, &policy, ¶ms) == 0) |
397 | { |
398 | if ((priority_max = __gthrw_(sched_get_priority_max)__gthrw_sched_get_priority_max (policy)) == -1) |
399 | return -1; |
400 | |
401 | if ((priority_min = __gthrw_(sched_get_priority_min)__gthrw_sched_get_priority_min (policy)) == -1) |
402 | return -1; |
403 | |
404 | if (priority > priority_max) |
405 | priority = priority_max; |
406 | else if (priority < priority_min) |
407 | priority = priority_min; |
408 | params.sched_prioritysched_priority = priority; |
409 | |
410 | /* |
411 | * The solaris 7 and several other man pages incorrectly state that |
412 | * this should be a pointer to policy but pthread.h is universally |
413 | * at odds with this. |
414 | */ |
415 | if (__gthrw_(pthread_setschedparam)__gthrw_pthread_setschedparam (thread_id, policy, ¶ms) == 0) |
416 | return 0; |
417 | } |
418 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
419 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
420 | return -1; |
421 | } |
422 | } |
423 | |
424 | /* Return the current thread's priority. */ |
425 | static inline int |
426 | __gthread_objc_thread_get_priority (void) |
427 | { |
428 | #ifdef _POSIX_PRIORITY_SCHEDULING200809L |
429 | #ifdef _POSIX_THREAD_PRIORITY_SCHEDULING200809L |
430 | if (__gthread_active_p ()) |
431 | { |
432 | int policy; |
433 | struct sched_param params; |
434 | |
435 | if (__gthrw_(pthread_getschedparam)__gthrw_pthread_getschedparam (__gthrw_(pthread_self)__gthrw_pthread_self (), &policy, ¶ms) == 0) |
436 | return params.sched_prioritysched_priority; |
437 | else |
438 | return -1; |
439 | } |
440 | else |
441 | #endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
442 | #endif /* _POSIX_PRIORITY_SCHEDULING */ |
443 | return OBJC_THREAD_INTERACTIVE_PRIORITY; |
444 | } |
445 | |
446 | /* Yield our process time to another thread. */ |
447 | static inline void |
448 | __gthread_objc_thread_yield (void) |
449 | { |
450 | if (__gthread_active_p ()) |
451 | __gthrw_(sched_yield)__gthrw_sched_yield (); |
452 | } |
453 | |
454 | /* Terminate the current thread. */ |
455 | static inline int |
456 | __gthread_objc_thread_exit (void) |
457 | { |
458 | if (__gthread_active_p ()) |
459 | /* exit the thread */ |
460 | __gthrw_(pthread_exit)__gthrw_pthread_exit (&__objc_thread_exit_status); |
461 | |
462 | /* Failed if we reached here */ |
463 | return -1; |
464 | } |
465 | |
466 | /* Returns an integer value which uniquely describes a thread. */ |
467 | static inline objc_thread_t |
468 | __gthread_objc_thread_id (void) |
469 | { |
470 | if (__gthread_active_p ()) |
471 | return (objc_thread_t) __gthrw_(pthread_self)__gthrw_pthread_self (); |
472 | else |
473 | return (objc_thread_t) 1; |
474 | } |
475 | |
476 | /* Sets the thread's local storage pointer. */ |
477 | static inline int |
478 | __gthread_objc_thread_set_data (void *value) |
479 | { |
480 | if (__gthread_active_p ()) |
481 | return __gthrw_(pthread_setspecific)__gthrw_pthread_setspecific (_objc_thread_storage, value); |
482 | else |
483 | { |
484 | thread_local_storage = value; |
485 | return 0; |
486 | } |
487 | } |
488 | |
489 | /* Returns the thread's local storage pointer. */ |
490 | static inline void * |
491 | __gthread_objc_thread_get_data (void) |
492 | { |
493 | if (__gthread_active_p ()) |
494 | return __gthrw_(pthread_getspecific)__gthrw_pthread_getspecific (_objc_thread_storage); |
495 | else |
496 | return thread_local_storage; |
497 | } |
498 | |
499 | /* Backend mutex functions */ |
500 | |
501 | /* Allocate a mutex. */ |
502 | static inline int |
503 | __gthread_objc_mutex_allocate (objc_mutex_t mutex) |
504 | { |
505 | if (__gthread_active_p ()) |
506 | { |
507 | mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); |
508 | |
509 | if (__gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init ((pthread_mutex_t *) mutex->backend, NULL__null)) |
510 | { |
511 | objc_free (mutex->backend); |
512 | mutex->backend = NULL__null; |
513 | return -1; |
514 | } |
515 | } |
516 | |
517 | return 0; |
518 | } |
519 | |
520 | /* Deallocate a mutex. */ |
521 | static inline int |
522 | __gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
523 | { |
524 | if (__gthread_active_p ()) |
525 | { |
526 | int count; |
527 | |
528 | /* |
529 | * Posix Threads specifically require that the thread be unlocked |
530 | * for __gthrw_(pthread_mutex_destroy) to work. |
531 | */ |
532 | |
533 | do |
534 | { |
535 | count = __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend); |
536 | if (count < 0) |
537 | return -1; |
538 | } |
539 | while (count); |
540 | |
541 | if (__gthrw_(pthread_mutex_destroy)__gthrw_pthread_mutex_destroy ((pthread_mutex_t *) mutex->backend)) |
542 | return -1; |
543 | |
544 | objc_free (mutex->backend); |
545 | mutex->backend = NULL__null; |
546 | } |
547 | return 0; |
548 | } |
549 | |
550 | /* Grab a lock on a mutex. */ |
551 | static inline int |
552 | __gthread_objc_mutex_lock (objc_mutex_t mutex) |
553 | { |
554 | if (__gthread_active_p () |
555 | && __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock ((pthread_mutex_t *) mutex->backend) != 0) |
556 | { |
557 | return -1; |
558 | } |
559 | |
560 | return 0; |
561 | } |
562 | |
563 | /* Try to grab a lock on a mutex. */ |
564 | static inline int |
565 | __gthread_objc_mutex_trylock (objc_mutex_t mutex) |
566 | { |
567 | if (__gthread_active_p () |
568 | && __gthrw_(pthread_mutex_trylock)__gthrw_pthread_mutex_trylock ((pthread_mutex_t *) mutex->backend) != 0) |
569 | { |
570 | return -1; |
571 | } |
572 | |
573 | return 0; |
574 | } |
575 | |
576 | /* Unlock the mutex */ |
577 | static inline int |
578 | __gthread_objc_mutex_unlock (objc_mutex_t mutex) |
579 | { |
580 | if (__gthread_active_p () |
581 | && __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock ((pthread_mutex_t *) mutex->backend) != 0) |
582 | { |
583 | return -1; |
584 | } |
585 | |
586 | return 0; |
587 | } |
588 | |
589 | /* Backend condition mutex functions */ |
590 | |
591 | /* Allocate a condition. */ |
592 | static inline int |
593 | __gthread_objc_condition_allocate (objc_condition_t condition) |
594 | { |
595 | if (__gthread_active_p ()) |
596 | { |
597 | condition->backend = objc_malloc (sizeof (pthread_cond_t)); |
598 | |
599 | if (__gthrw_(pthread_cond_init)__gthrw_pthread_cond_init ((pthread_cond_t *) condition->backend, NULL__null)) |
600 | { |
601 | objc_free (condition->backend); |
602 | condition->backend = NULL__null; |
603 | return -1; |
604 | } |
605 | } |
606 | |
607 | return 0; |
608 | } |
609 | |
610 | /* Deallocate a condition. */ |
611 | static inline int |
612 | __gthread_objc_condition_deallocate (objc_condition_t condition) |
613 | { |
614 | if (__gthread_active_p ()) |
615 | { |
616 | if (__gthrw_(pthread_cond_destroy)__gthrw_pthread_cond_destroy ((pthread_cond_t *) condition->backend)) |
617 | return -1; |
618 | |
619 | objc_free (condition->backend); |
620 | condition->backend = NULL__null; |
621 | } |
622 | return 0; |
623 | } |
624 | |
625 | /* Wait on the condition */ |
626 | static inline int |
627 | __gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
628 | { |
629 | if (__gthread_active_p ()) |
630 | return __gthrw_(pthread_cond_wait)__gthrw_pthread_cond_wait ((pthread_cond_t *) condition->backend, |
631 | (pthread_mutex_t *) mutex->backend); |
632 | else |
633 | return 0; |
634 | } |
635 | |
636 | /* Wake up all threads waiting on this condition. */ |
637 | static inline int |
638 | __gthread_objc_condition_broadcast (objc_condition_t condition) |
639 | { |
640 | if (__gthread_active_p ()) |
641 | return __gthrw_(pthread_cond_broadcast)__gthrw_pthread_cond_broadcast ((pthread_cond_t *) condition->backend); |
642 | else |
643 | return 0; |
644 | } |
645 | |
646 | /* Wake up one thread waiting on this condition. */ |
647 | static inline int |
648 | __gthread_objc_condition_signal (objc_condition_t condition) |
649 | { |
650 | if (__gthread_active_p ()) |
651 | return __gthrw_(pthread_cond_signal)__gthrw_pthread_cond_signal ((pthread_cond_t *) condition->backend); |
652 | else |
653 | return 0; |
654 | } |
655 | |
656 | #else /* _LIBOBJC */ |
657 | |
658 | static inline int |
659 | __gthread_create (__gthread_t *__threadid, void *(*__func) (void*), |
660 | void *__args) |
661 | { |
662 | return __gthrw_(pthread_create)__gthrw_pthread_create (__threadid, NULL__null, __func, __args); |
663 | } |
664 | |
665 | static inline int |
666 | __gthread_join (__gthread_t __threadid, void **__value_ptr) |
667 | { |
668 | return __gthrw_(pthread_join)__gthrw_pthread_join (__threadid, __value_ptr); |
669 | } |
670 | |
671 | static inline int |
672 | __gthread_detach (__gthread_t __threadid) |
673 | { |
674 | return __gthrw_(pthread_detach)__gthrw_pthread_detach (__threadid); |
675 | } |
676 | |
677 | static inline int |
678 | __gthread_equal (__gthread_t __t1, __gthread_t __t2) |
679 | { |
680 | return __gthrw_(pthread_equal)__gthrw_pthread_equal (__t1, __t2); |
681 | } |
682 | |
683 | static inline __gthread_t |
684 | __gthread_self (void) |
685 | { |
686 | return __gthrw_(pthread_self)__gthrw_pthread_self (); |
687 | } |
688 | |
689 | static inline int |
690 | __gthread_yield (void) |
691 | { |
692 | return __gthrw_(sched_yield)__gthrw_sched_yield (); |
693 | } |
694 | |
695 | static inline int |
696 | __gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
697 | { |
698 | if (__gthread_active_p ()) |
699 | return __gthrw_(pthread_once)__gthrw_pthread_once (__once, __func); |
700 | else |
701 | return -1; |
702 | } |
703 | |
704 | static inline int |
705 | __gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) |
706 | { |
707 | return __gthrw_(pthread_key_create)__gthrw_pthread_key_create (__key, __dtor); |
708 | } |
709 | |
710 | static inline int |
711 | __gthread_key_delete (__gthread_key_t __key) |
712 | { |
713 | return __gthrw_(pthread_key_delete)__gthrw_pthread_key_delete (__key); |
714 | } |
715 | |
716 | static inline void * |
717 | __gthread_getspecific (__gthread_key_t __key) |
718 | { |
719 | return __gthrw_(pthread_getspecific)__gthrw_pthread_getspecific (__key); |
720 | } |
721 | |
722 | static inline int |
723 | __gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
724 | { |
725 | return __gthrw_(pthread_setspecific)__gthrw_pthread_setspecific (__key, __ptr); |
726 | } |
727 | |
728 | static inline void |
729 | __gthread_mutex_init_function (__gthread_mutex_t *__mutex) |
730 | { |
731 | if (__gthread_active_p ()) |
732 | __gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init (__mutex, NULL__null); |
733 | } |
734 | |
735 | static inline int |
736 | __gthread_mutex_destroy (__gthread_mutex_t *__mutex) |
737 | { |
738 | if (__gthread_active_p ()) |
739 | return __gthrw_(pthread_mutex_destroy)__gthrw_pthread_mutex_destroy (__mutex); |
740 | else |
741 | return 0; |
742 | } |
743 | |
744 | static inline int |
745 | __gthread_mutex_lock (__gthread_mutex_t *__mutex) |
746 | { |
747 | if (__gthread_active_p ()) |
748 | return __gthrw_(pthread_mutex_lock)__gthrw_pthread_mutex_lock (__mutex); |
749 | else |
750 | return 0; |
751 | } |
752 | |
753 | static inline int |
754 | __gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
755 | { |
756 | if (__gthread_active_p ()) |
757 | return __gthrw_(pthread_mutex_trylock)__gthrw_pthread_mutex_trylock (__mutex); |
758 | else |
759 | return 0; |
760 | } |
761 | |
762 | #if _GTHREAD_USE_MUTEX_TIMEDLOCK1 |
763 | static inline int |
764 | __gthread_mutex_timedlock (__gthread_mutex_t *__mutex, |
765 | const __gthread_time_t *__abs_timeout) |
766 | { |
767 | if (__gthread_active_p ()) |
768 | return __gthrw_(pthread_mutex_timedlock)__gthrw_pthread_mutex_timedlock (__mutex, __abs_timeout); |
769 | else |
770 | return 0; |
771 | } |
772 | #endif |
773 | |
774 | static inline int |
775 | __gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
776 | { |
777 | if (__gthread_active_p ()) |
778 | return __gthrw_(pthread_mutex_unlock)__gthrw_pthread_mutex_unlock (__mutex); |
779 | else |
780 | return 0; |
781 | } |
782 | |
783 | #if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP{ { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, 0, { 0, 0 } } }) \ |
784 | || defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC) |
785 | static inline int |
786 | __gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
787 | { |
788 | if (__gthread_active_p ()) |
789 | { |
790 | pthread_mutexattr_t __attr; |
791 | int __r; |
792 | |
793 | __r = __gthrw_(pthread_mutexattr_init)__gthrw_pthread_mutexattr_init (&__attr); |
794 | if (!__r) |
795 | __r = __gthrw_(pthread_mutexattr_settype)__gthrw_pthread_mutexattr_settype (&__attr, |
796 | PTHREAD_MUTEX_RECURSIVE); |
797 | if (!__r) |
798 | __r = __gthrw_(pthread_mutex_init)__gthrw_pthread_mutex_init (__mutex, &__attr); |
799 | if (!__r) |
800 | __r = __gthrw_(pthread_mutexattr_destroy)__gthrw_pthread_mutexattr_destroy (&__attr); |
801 | return __r; |
802 | } |
803 | return 0; |
804 | } |
805 | #endif |
806 | |
807 | static inline int |
808 | __gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
809 | { |
810 | return __gthread_mutex_lock (__mutex); |
811 | } |
812 | |
813 | static inline int |
814 | __gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
815 | { |
816 | return __gthread_mutex_trylock (__mutex); |
817 | } |
818 | |
819 | #if _GTHREAD_USE_MUTEX_TIMEDLOCK1 |
820 | static inline int |
821 | __gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex, |
822 | const __gthread_time_t *__abs_timeout) |
823 | { |
824 | return __gthread_mutex_timedlock (__mutex, __abs_timeout); |
825 | } |
826 | #endif |
827 | |
828 | static inline int |
829 | __gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
830 | { |
831 | return __gthread_mutex_unlock (__mutex); |
832 | } |
833 | |
834 | static inline int |
835 | __gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) |
836 | { |
837 | return __gthread_mutex_destroy (__mutex); |
838 | } |
839 | |
840 | #ifdef _GTHREAD_USE_COND_INIT_FUNC |
841 | static inline void |
842 | __gthread_cond_init_function (__gthread_cond_t *__cond) |
843 | { |
844 | if (__gthread_active_p ()) |
845 | __gthrw_(pthread_cond_init)__gthrw_pthread_cond_init (__cond, NULL__null); |
846 | } |
847 | #endif |
848 | |
849 | static inline int |
850 | __gthread_cond_broadcast (__gthread_cond_t *__cond) |
851 | { |
852 | return __gthrw_(pthread_cond_broadcast)__gthrw_pthread_cond_broadcast (__cond); |
853 | } |
854 | |
855 | static inline int |
856 | __gthread_cond_signal (__gthread_cond_t *__cond) |
857 | { |
858 | return __gthrw_(pthread_cond_signal)__gthrw_pthread_cond_signal (__cond); |
859 | } |
860 | |
861 | static inline int |
862 | __gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) |
863 | { |
864 | return __gthrw_(pthread_cond_wait)__gthrw_pthread_cond_wait (__cond, __mutex); |
865 | } |
866 | |
867 | static inline int |
868 | __gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, |
869 | const __gthread_time_t *__abs_timeout) |
870 | { |
871 | return __gthrw_(pthread_cond_timedwait)__gthrw_pthread_cond_timedwait (__cond, __mutex, __abs_timeout); |
872 | } |
873 | |
874 | static inline int |
875 | __gthread_cond_wait_recursive (__gthread_cond_t *__cond, |
876 | __gthread_recursive_mutex_t *__mutex) |
877 | { |
878 | return __gthread_cond_wait (__cond, __mutex); |
879 | } |
880 | |
881 | static inline int |
882 | __gthread_cond_destroy (__gthread_cond_t* __cond) |
883 | { |
884 | return __gthrw_(pthread_cond_destroy)__gthrw_pthread_cond_destroy (__cond); |
885 | } |
886 | |
887 | #endif /* _LIBOBJC */ |
888 | |
889 | #endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */ |
1 | //===- llvm/ExecutionEngine/Orc/RPCSerialization.h --------------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H |
11 | #define LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H |
12 | |
13 | #include "OrcError.h" |
14 | #include "llvm/Support/thread.h" |
15 | #include <map> |
16 | #include <mutex> |
17 | #include <sstream> |
18 | |
19 | namespace llvm { |
20 | namespace orc { |
21 | namespace rpc { |
22 | |
23 | template <typename T> |
24 | class RPCTypeName; |
25 | |
26 | /// TypeNameSequence is a utility for rendering sequences of types to a string |
27 | /// by rendering each type, separated by ", ". |
28 | template <typename... ArgTs> class RPCTypeNameSequence {}; |
29 | |
30 | /// Render an empty TypeNameSequence to an ostream. |
31 | template <typename OStream> |
32 | OStream &operator<<(OStream &OS, const RPCTypeNameSequence<> &V) { |
33 | return OS; |
34 | } |
35 | |
36 | /// Render a TypeNameSequence of a single type to an ostream. |
37 | template <typename OStream, typename ArgT> |
38 | OStream &operator<<(OStream &OS, const RPCTypeNameSequence<ArgT> &V) { |
39 | OS << RPCTypeName<ArgT>::getName(); |
40 | return OS; |
41 | } |
42 | |
43 | /// Render a TypeNameSequence of more than one type to an ostream. |
44 | template <typename OStream, typename ArgT1, typename ArgT2, typename... ArgTs> |
45 | OStream& |
46 | operator<<(OStream &OS, const RPCTypeNameSequence<ArgT1, ArgT2, ArgTs...> &V) { |
47 | OS << RPCTypeName<ArgT1>::getName() << ", " |
48 | << RPCTypeNameSequence<ArgT2, ArgTs...>(); |
49 | return OS; |
50 | } |
51 | |
52 | template <> |
53 | class RPCTypeName<void> { |
54 | public: |
55 | static const char* getName() { return "void"; } |
56 | }; |
57 | |
58 | template <> |
59 | class RPCTypeName<int8_t> { |
60 | public: |
61 | static const char* getName() { return "int8_t"; } |
62 | }; |
63 | |
64 | template <> |
65 | class RPCTypeName<uint8_t> { |
66 | public: |
67 | static const char* getName() { return "uint8_t"; } |
68 | }; |
69 | |
70 | template <> |
71 | class RPCTypeName<int16_t> { |
72 | public: |
73 | static const char* getName() { return "int16_t"; } |
74 | }; |
75 | |
76 | template <> |
77 | class RPCTypeName<uint16_t> { |
78 | public: |
79 | static const char* getName() { return "uint16_t"; } |
80 | }; |
81 | |
82 | template <> |
83 | class RPCTypeName<int32_t> { |
84 | public: |
85 | static const char* getName() { return "int32_t"; } |
86 | }; |
87 | |
88 | template <> |
89 | class RPCTypeName<uint32_t> { |
90 | public: |
91 | static const char* getName() { return "uint32_t"; } |
92 | }; |
93 | |
94 | template <> |
95 | class RPCTypeName<int64_t> { |
96 | public: |
97 | static const char* getName() { return "int64_t"; } |
98 | }; |
99 | |
100 | template <> |
101 | class RPCTypeName<uint64_t> { |
102 | public: |
103 | static const char* getName() { return "uint64_t"; } |
104 | }; |
105 | |
106 | template <> |
107 | class RPCTypeName<bool> { |
108 | public: |
109 | static const char* getName() { return "bool"; } |
110 | }; |
111 | |
112 | template <> |
113 | class RPCTypeName<std::string> { |
114 | public: |
115 | static const char* getName() { return "std::string"; } |
116 | }; |
117 | |
118 | template <> |
119 | class RPCTypeName<Error> { |
120 | public: |
121 | static const char* getName() { return "Error"; } |
122 | }; |
123 | |
124 | template <typename T> |
125 | class RPCTypeName<Expected<T>> { |
126 | public: |
127 | static const char* getName() { |
128 | std::lock_guard<std::mutex> Lock(NameMutex); |
129 | if (Name.empty()) |
130 | raw_string_ostream(Name) << "Expected<" |
131 | << RPCTypeNameSequence<T>() |
132 | << ">"; |
133 | return Name.data(); |
134 | } |
135 | |
136 | private: |
137 | static std::mutex NameMutex; |
138 | static std::string Name; |
139 | }; |
140 | |
141 | template <typename T> |
142 | std::mutex RPCTypeName<Expected<T>>::NameMutex; |
143 | |
144 | template <typename T> |
145 | std::string RPCTypeName<Expected<T>>::Name; |
146 | |
147 | template <typename T1, typename T2> |
148 | class RPCTypeName<std::pair<T1, T2>> { |
149 | public: |
150 | static const char* getName() { |
151 | std::lock_guard<std::mutex> Lock(NameMutex); |
152 | if (Name.empty()) |
153 | raw_string_ostream(Name) << "std::pair<" << RPCTypeNameSequence<T1, T2>() |
154 | << ">"; |
155 | return Name.data(); |
156 | } |
157 | private: |
158 | static std::mutex NameMutex; |
159 | static std::string Name; |
160 | }; |
161 | |
162 | template <typename T1, typename T2> |
163 | std::mutex RPCTypeName<std::pair<T1, T2>>::NameMutex; |
164 | template <typename T1, typename T2> |
165 | std::string RPCTypeName<std::pair<T1, T2>>::Name; |
166 | |
167 | template <typename... ArgTs> |
168 | class RPCTypeName<std::tuple<ArgTs...>> { |
169 | public: |
170 | static const char* getName() { |
171 | std::lock_guard<std::mutex> Lock(NameMutex); |
172 | if (Name.empty()) |
173 | raw_string_ostream(Name) << "std::tuple<" |
174 | << RPCTypeNameSequence<ArgTs...>() << ">"; |
175 | return Name.data(); |
176 | } |
177 | private: |
178 | static std::mutex NameMutex; |
179 | static std::string Name; |
180 | }; |
181 | |
182 | template <typename... ArgTs> |
183 | std::mutex RPCTypeName<std::tuple<ArgTs...>>::NameMutex; |
184 | template <typename... ArgTs> |
185 | std::string RPCTypeName<std::tuple<ArgTs...>>::Name; |
186 | |
187 | template <typename T> |
188 | class RPCTypeName<std::vector<T>> { |
189 | public: |
190 | static const char*getName() { |
191 | std::lock_guard<std::mutex> Lock(NameMutex); |
192 | if (Name.empty()) |
193 | raw_string_ostream(Name) << "std::vector<" << RPCTypeName<T>::getName() |
194 | << ">"; |
195 | return Name.data(); |
196 | } |
197 | |
198 | private: |
199 | static std::mutex NameMutex; |
200 | static std::string Name; |
201 | }; |
202 | |
203 | template <typename T> |
204 | std::mutex RPCTypeName<std::vector<T>>::NameMutex; |
205 | template <typename T> |
206 | std::string RPCTypeName<std::vector<T>>::Name; |
207 | |
208 | |
209 | /// The SerializationTraits<ChannelT, T> class describes how to serialize and |
210 | /// deserialize an instance of type T to/from an abstract channel of type |
211 | /// ChannelT. It also provides a representation of the type's name via the |
212 | /// getName method. |
213 | /// |
214 | /// Specializations of this class should provide the following functions: |
215 | /// |
216 | /// @code{.cpp} |
217 | /// |
218 | /// static const char* getName(); |
219 | /// static Error serialize(ChannelT&, const T&); |
220 | /// static Error deserialize(ChannelT&, T&); |
221 | /// |
222 | /// @endcode |
223 | /// |
224 | /// The third argument of SerializationTraits is intended to support SFINAE. |
225 | /// E.g.: |
226 | /// |
227 | /// @code{.cpp} |
228 | /// |
229 | /// class MyVirtualChannel { ... }; |
230 | /// |
231 | /// template <DerivedChannelT> |
232 | /// class SerializationTraits<DerivedChannelT, bool, |
233 | /// typename std::enable_if< |
234 | /// std::is_base_of<VirtChannel, DerivedChannel>::value |
235 | /// >::type> { |
236 | /// public: |
237 | /// static const char* getName() { ... }; |
238 | /// } |
239 | /// |
240 | /// @endcode |
241 | template <typename ChannelT, typename WireType, |
242 | typename ConcreteType = WireType, typename = void> |
243 | class SerializationTraits; |
244 | |
245 | template <typename ChannelT> |
246 | class SequenceTraits { |
247 | public: |
248 | static Error emitSeparator(ChannelT &C) { return Error::success(); } |
249 | static Error consumeSeparator(ChannelT &C) { return Error::success(); } |
250 | }; |
251 | |
252 | /// Utility class for serializing sequences of values of varying types. |
253 | /// Specializations of this class contain 'serialize' and 'deserialize' methods |
254 | /// for the given channel. The ArgTs... list will determine the "over-the-wire" |
255 | /// types to be serialized. The serialize and deserialize methods take a list |
256 | /// CArgTs... ("caller arg types") which must be the same length as ArgTs..., |
257 | /// but may be different types from ArgTs, provided that for each CArgT there |
258 | /// is a SerializationTraits specialization |
259 | /// SerializeTraits<ChannelT, ArgT, CArgT> with methods that can serialize the |
260 | /// caller argument to over-the-wire value. |
261 | template <typename ChannelT, typename... ArgTs> |
262 | class SequenceSerialization; |
263 | |
264 | template <typename ChannelT> |
265 | class SequenceSerialization<ChannelT> { |
266 | public: |
267 | static Error serialize(ChannelT &C) { return Error::success(); } |
268 | static Error deserialize(ChannelT &C) { return Error::success(); } |
269 | }; |
270 | |
271 | template <typename ChannelT, typename ArgT> |
272 | class SequenceSerialization<ChannelT, ArgT> { |
273 | public: |
274 | |
275 | template <typename CArgT> |
276 | static Error serialize(ChannelT &C, CArgT &&CArg) { |
277 | return SerializationTraits<ChannelT, ArgT, |
278 | typename std::decay<CArgT>::type>:: |
279 | serialize(C, std::forward<CArgT>(CArg)); |
280 | } |
281 | |
282 | template <typename CArgT> |
283 | static Error deserialize(ChannelT &C, CArgT &CArg) { |
284 | return SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg); |
285 | } |
286 | }; |
287 | |
288 | template <typename ChannelT, typename ArgT, typename... ArgTs> |
289 | class SequenceSerialization<ChannelT, ArgT, ArgTs...> { |
290 | public: |
291 | |
292 | template <typename CArgT, typename... CArgTs> |
293 | static Error serialize(ChannelT &C, CArgT &&CArg, |
294 | CArgTs &&... CArgs) { |
295 | if (auto Err = |
296 | SerializationTraits<ChannelT, ArgT, typename std::decay<CArgT>::type>:: |
297 | serialize(C, std::forward<CArgT>(CArg))) |
298 | return Err; |
299 | if (auto Err = SequenceTraits<ChannelT>::emitSeparator(C)) |
300 | return Err; |
301 | return SequenceSerialization<ChannelT, ArgTs...>:: |
302 | serialize(C, std::forward<CArgTs>(CArgs)...); |
303 | } |
304 | |
305 | template <typename CArgT, typename... CArgTs> |
306 | static Error deserialize(ChannelT &C, CArgT &CArg, |
307 | CArgTs &... CArgs) { |
308 | if (auto Err = |
309 | SerializationTraits<ChannelT, ArgT, CArgT>::deserialize(C, CArg)) |
310 | return Err; |
311 | if (auto Err = SequenceTraits<ChannelT>::consumeSeparator(C)) |
312 | return Err; |
313 | return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, CArgs...); |
314 | } |
315 | }; |
316 | |
317 | template <typename ChannelT, typename... ArgTs> |
318 | Error serializeSeq(ChannelT &C, ArgTs &&... Args) { |
319 | return SequenceSerialization<ChannelT, typename std::decay<ArgTs>::type...>:: |
320 | serialize(C, std::forward<ArgTs>(Args)...); |
321 | } |
322 | |
323 | template <typename ChannelT, typename... ArgTs> |
324 | Error deserializeSeq(ChannelT &C, ArgTs &... Args) { |
325 | return SequenceSerialization<ChannelT, ArgTs...>::deserialize(C, Args...); |
326 | } |
327 | |
328 | template <typename ChannelT> |
329 | class SerializationTraits<ChannelT, Error> { |
330 | public: |
331 | |
332 | using WrappedErrorSerializer = |
333 | std::function<Error(ChannelT &C, const ErrorInfoBase&)>; |
334 | |
335 | using WrappedErrorDeserializer = |
336 | std::function<Error(ChannelT &C, Error &Err)>; |
337 | |
338 | template <typename ErrorInfoT, typename SerializeFtor, |
339 | typename DeserializeFtor> |
340 | static void registerErrorType(std::string Name, SerializeFtor Serialize, |
341 | DeserializeFtor Deserialize) { |
342 | assert(!Name.empty() &&(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value" ) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 343, __extension__ __PRETTY_FUNCTION__)) |
343 | "The empty string is reserved for the Success value")(static_cast <bool> (!Name.empty() && "The empty string is reserved for the Success value" ) ? void (0) : __assert_fail ("!Name.empty() && \"The empty string is reserved for the Success value\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 343, __extension__ __PRETTY_FUNCTION__)); |
344 | |
345 | const std::string *KeyName = nullptr; |
346 | { |
347 | // We're abusing the stability of std::map here: We take a reference to the |
348 | // key of the deserializers map to save us from duplicating the string in |
349 | // the serializer. This should be changed to use a stringpool if we switch |
350 | // to a map type that may move keys in memory. |
351 | std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex); |
352 | auto I = |
353 | Deserializers.insert(Deserializers.begin(), |
354 | std::make_pair(std::move(Name), |
355 | std::move(Deserialize))); |
356 | KeyName = &I->first; |
357 | } |
358 | |
359 | { |
360 | assert(KeyName != nullptr && "No keyname pointer")(static_cast <bool> (KeyName != nullptr && "No keyname pointer" ) ? void (0) : __assert_fail ("KeyName != nullptr && \"No keyname pointer\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 360, __extension__ __PRETTY_FUNCTION__)); |
361 | std::lock_guard<std::recursive_mutex> Lock(SerializersMutex); |
362 | // FIXME: Move capture Serialize once we have C++14. |
363 | Serializers[ErrorInfoT::classID()] = |
364 | [KeyName, Serialize](ChannelT &C, const ErrorInfoBase &EIB) -> Error { |
365 | assert(EIB.dynamicClassID() == ErrorInfoT::classID() &&(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT ::classID() && "Serializer called for wrong error type" ) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 366, __extension__ __PRETTY_FUNCTION__)) |
366 | "Serializer called for wrong error type")(static_cast <bool> (EIB.dynamicClassID() == ErrorInfoT ::classID() && "Serializer called for wrong error type" ) ? void (0) : __assert_fail ("EIB.dynamicClassID() == ErrorInfoT::classID() && \"Serializer called for wrong error type\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 366, __extension__ __PRETTY_FUNCTION__)); |
367 | if (auto Err = serializeSeq(C, *KeyName)) |
368 | return Err; |
369 | return Serialize(C, static_cast<const ErrorInfoT &>(EIB)); |
370 | }; |
371 | } |
372 | } |
373 | |
374 | static Error serialize(ChannelT &C, Error &&Err) { |
375 | std::lock_guard<std::recursive_mutex> Lock(SerializersMutex); |
376 | |
377 | if (!Err) |
378 | return serializeSeq(C, std::string()); |
379 | |
380 | return handleErrors(std::move(Err), |
381 | [&C](const ErrorInfoBase &EIB) { |
382 | auto SI = Serializers.find(EIB.dynamicClassID()); |
383 | if (SI == Serializers.end()) |
384 | return serializeAsStringError(C, EIB); |
385 | return (SI->second)(C, EIB); |
386 | }); |
387 | } |
388 | |
389 | static Error deserialize(ChannelT &C, Error &Err) { |
390 | std::lock_guard<std::recursive_mutex> Lock(DeserializersMutex); |
391 | |
392 | std::string Key; |
393 | if (auto Err = deserializeSeq(C, Key)) |
394 | return Err; |
395 | |
396 | if (Key.empty()) { |
397 | ErrorAsOutParameter EAO(&Err); |
398 | Err = Error::success(); |
399 | return Error::success(); |
400 | } |
401 | |
402 | auto DI = Deserializers.find(Key); |
403 | assert(DI != Deserializers.end() && "No deserializer for error type")(static_cast <bool> (DI != Deserializers.end() && "No deserializer for error type") ? void (0) : __assert_fail ("DI != Deserializers.end() && \"No deserializer for error type\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/ExecutionEngine/Orc/RPCSerialization.h" , 403, __extension__ __PRETTY_FUNCTION__)); |
404 | return (DI->second)(C, Err); |
405 | } |
406 | |
407 | private: |
408 | |
409 | static Error serializeAsStringError(ChannelT &C, const ErrorInfoBase &EIB) { |
410 | std::string ErrMsg; |
411 | { |
412 | raw_string_ostream ErrMsgStream(ErrMsg); |
413 | EIB.log(ErrMsgStream); |
414 | } |
415 | return serialize(C, make_error<StringError>(std::move(ErrMsg), |
416 | inconvertibleErrorCode())); |
417 | } |
418 | |
419 | static std::recursive_mutex SerializersMutex; |
420 | static std::recursive_mutex DeserializersMutex; |
421 | static std::map<const void*, WrappedErrorSerializer> Serializers; |
422 | static std::map<std::string, WrappedErrorDeserializer> Deserializers; |
423 | }; |
424 | |
425 | template <typename ChannelT> |
426 | std::recursive_mutex SerializationTraits<ChannelT, Error>::SerializersMutex; |
427 | |
428 | template <typename ChannelT> |
429 | std::recursive_mutex SerializationTraits<ChannelT, Error>::DeserializersMutex; |
430 | |
431 | template <typename ChannelT> |
432 | std::map<const void*, |
433 | typename SerializationTraits<ChannelT, Error>::WrappedErrorSerializer> |
434 | SerializationTraits<ChannelT, Error>::Serializers; |
435 | |
436 | template <typename ChannelT> |
437 | std::map<std::string, |
438 | typename SerializationTraits<ChannelT, Error>::WrappedErrorDeserializer> |
439 | SerializationTraits<ChannelT, Error>::Deserializers; |
440 | |
441 | /// Registers a serializer and deserializer for the given error type on the |
442 | /// given channel type. |
443 | template <typename ChannelT, typename ErrorInfoT, typename SerializeFtor, |
444 | typename DeserializeFtor> |
445 | void registerErrorSerialization(std::string Name, SerializeFtor &&Serialize, |
446 | DeserializeFtor &&Deserialize) { |
447 | SerializationTraits<ChannelT, Error>::template registerErrorType<ErrorInfoT>( |
448 | std::move(Name), |
449 | std::forward<SerializeFtor>(Serialize), |
450 | std::forward<DeserializeFtor>(Deserialize)); |
451 | } |
452 | |
453 | /// Registers serialization/deserialization for StringError. |
454 | template <typename ChannelT> |
455 | void registerStringError() { |
456 | static bool AlreadyRegistered = false; |
457 | if (!AlreadyRegistered) { |
458 | registerErrorSerialization<ChannelT, StringError>( |
459 | "StringError", |
460 | [](ChannelT &C, const StringError &SE) { |
461 | return serializeSeq(C, SE.getMessage()); |
462 | }, |
463 | [](ChannelT &C, Error &Err) -> Error { |
464 | ErrorAsOutParameter EAO(&Err); |
465 | std::string Msg; |
466 | if (auto E2 = deserializeSeq(C, Msg)) |
467 | return E2; |
468 | Err = |
469 | make_error<StringError>(std::move(Msg), |
470 | orcError( |
471 | OrcErrorCode::UnknownErrorCodeFromRemote)); |
472 | return Error::success(); |
473 | }); |
474 | AlreadyRegistered = true; |
475 | } |
476 | } |
477 | |
478 | /// SerializationTraits for Expected<T1> from an Expected<T2>. |
479 | template <typename ChannelT, typename T1, typename T2> |
480 | class SerializationTraits<ChannelT, Expected<T1>, Expected<T2>> { |
481 | public: |
482 | |
483 | static Error serialize(ChannelT &C, Expected<T2> &&ValOrErr) { |
484 | if (ValOrErr) { |
485 | if (auto Err = serializeSeq(C, true)) |
486 | return Err; |
487 | return SerializationTraits<ChannelT, T1, T2>::serialize(C, *ValOrErr); |
488 | } |
489 | if (auto Err = serializeSeq(C, false)) |
490 | return Err; |
491 | return serializeSeq(C, ValOrErr.takeError()); |
492 | } |
493 | |
494 | static Error deserialize(ChannelT &C, Expected<T2> &ValOrErr) { |
495 | ExpectedAsOutParameter<T2> EAO(&ValOrErr); |
496 | bool HasValue; |
497 | if (auto Err = deserializeSeq(C, HasValue)) |
498 | return Err; |
499 | if (HasValue) |
500 | return SerializationTraits<ChannelT, T1, T2>::deserialize(C, *ValOrErr); |
501 | Error Err = Error::success(); |
502 | if (auto E2 = deserializeSeq(C, Err)) |
503 | return E2; |
504 | ValOrErr = std::move(Err); |
505 | return Error::success(); |
506 | } |
507 | }; |
508 | |
509 | /// SerializationTraits for Expected<T1> from a T2. |
510 | template <typename ChannelT, typename T1, typename T2> |
511 | class SerializationTraits<ChannelT, Expected<T1>, T2> { |
512 | public: |
513 | |
514 | static Error serialize(ChannelT &C, T2 &&Val) { |
515 | return serializeSeq(C, Expected<T2>(std::forward<T2>(Val))); |
516 | } |
517 | }; |
518 | |
519 | /// SerializationTraits for Expected<T1> from an Error. |
520 | template <typename ChannelT, typename T> |
521 | class SerializationTraits<ChannelT, Expected<T>, Error> { |
522 | public: |
523 | |
524 | static Error serialize(ChannelT &C, Error &&Err) { |
525 | return serializeSeq(C, Expected<T>(std::move(Err))); |
526 | } |
527 | }; |
528 | |
529 | /// SerializationTraits default specialization for std::pair. |
530 | template <typename ChannelT, typename T1, typename T2> |
531 | class SerializationTraits<ChannelT, std::pair<T1, T2>> { |
532 | public: |
533 | static Error serialize(ChannelT &C, const std::pair<T1, T2> &V) { |
534 | return serializeSeq(C, V.first, V.second); |
535 | } |
536 | |
537 | static Error deserialize(ChannelT &C, std::pair<T1, T2> &V) { |
538 | return deserializeSeq(C, V.first, V.second); |
539 | } |
540 | }; |
541 | |
542 | /// SerializationTraits default specialization for std::tuple. |
543 | template <typename ChannelT, typename... ArgTs> |
544 | class SerializationTraits<ChannelT, std::tuple<ArgTs...>> { |
545 | public: |
546 | |
547 | /// RPC channel serialization for std::tuple. |
548 | static Error serialize(ChannelT &C, const std::tuple<ArgTs...> &V) { |
549 | return serializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>()); |
550 | } |
551 | |
552 | /// RPC channel deserialization for std::tuple. |
553 | static Error deserialize(ChannelT &C, std::tuple<ArgTs...> &V) { |
554 | return deserializeTupleHelper(C, V, llvm::index_sequence_for<ArgTs...>()); |
555 | } |
556 | |
557 | private: |
558 | // Serialization helper for std::tuple. |
559 | template <size_t... Is> |
560 | static Error serializeTupleHelper(ChannelT &C, const std::tuple<ArgTs...> &V, |
561 | llvm::index_sequence<Is...> _) { |
562 | return serializeSeq(C, std::get<Is>(V)...); |
563 | } |
564 | |
565 | // Serialization helper for std::tuple. |
566 | template <size_t... Is> |
567 | static Error deserializeTupleHelper(ChannelT &C, std::tuple<ArgTs...> &V, |
568 | llvm::index_sequence<Is...> _) { |
569 | return deserializeSeq(C, std::get<Is>(V)...); |
570 | } |
571 | }; |
572 | |
573 | /// SerializationTraits default specialization for std::vector. |
574 | template <typename ChannelT, typename T> |
575 | class SerializationTraits<ChannelT, std::vector<T>> { |
576 | public: |
577 | |
578 | /// Serialize a std::vector<T> from std::vector<T>. |
579 | static Error serialize(ChannelT &C, const std::vector<T> &V) { |
580 | if (auto Err = serializeSeq(C, static_cast<uint64_t>(V.size()))) |
581 | return Err; |
582 | |
583 | for (const auto &E : V) |
584 | if (auto Err = serializeSeq(C, E)) |
585 | return Err; |
586 | |
587 | return Error::success(); |
588 | } |
589 | |
590 | /// Deserialize a std::vector<T> to a std::vector<T>. |
591 | static Error deserialize(ChannelT &C, std::vector<T> &V) { |
592 | uint64_t Count = 0; |
593 | if (auto Err = deserializeSeq(C, Count)) |
594 | return Err; |
595 | |
596 | V.resize(Count); |
597 | for (auto &E : V) |
598 | if (auto Err = deserializeSeq(C, E)) |
599 | return Err; |
600 | |
601 | return Error::success(); |
602 | } |
603 | }; |
604 | |
605 | } // end namespace rpc |
606 | } // end namespace orc |
607 | } // end namespace llvm |
608 | |
609 | #endif // LLVM_EXECUTIONENGINE_ORC_RPCSERIALIZATION_H |
1 | //===- llvm/Support/Error.h - Recoverable error handling --------*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This file defines an API used to report recoverable errors. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #ifndef LLVM_SUPPORT_ERROR_H |
15 | #define LLVM_SUPPORT_ERROR_H |
16 | |
17 | #include "llvm/ADT/SmallVector.h" |
18 | #include "llvm/ADT/STLExtras.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/ADT/Twine.h" |
21 | #include "llvm/Config/abi-breaking.h" |
22 | #include "llvm/Support/AlignOf.h" |
23 | #include "llvm/Support/Compiler.h" |
24 | #include "llvm/Support/Debug.h" |
25 | #include "llvm/Support/ErrorHandling.h" |
26 | #include "llvm/Support/ErrorOr.h" |
27 | #include "llvm/Support/raw_ostream.h" |
28 | #include <algorithm> |
29 | #include <cassert> |
30 | #include <cstdint> |
31 | #include <cstdlib> |
32 | #include <functional> |
33 | #include <memory> |
34 | #include <new> |
35 | #include <string> |
36 | #include <system_error> |
37 | #include <type_traits> |
38 | #include <utility> |
39 | #include <vector> |
40 | |
41 | namespace llvm { |
42 | |
43 | class ErrorSuccess; |
44 | |
45 | /// Base class for error info classes. Do not extend this directly: Extend |
46 | /// the ErrorInfo template subclass instead. |
47 | class ErrorInfoBase { |
48 | public: |
49 | virtual ~ErrorInfoBase() = default; |
50 | |
51 | /// Print an error message to an output stream. |
52 | virtual void log(raw_ostream &OS) const = 0; |
53 | |
54 | /// Return the error message as a string. |
55 | virtual std::string message() const { |
56 | std::string Msg; |
57 | raw_string_ostream OS(Msg); |
58 | log(OS); |
59 | return OS.str(); |
60 | } |
61 | |
62 | /// Convert this error to a std::error_code. |
63 | /// |
64 | /// This is a temporary crutch to enable interaction with code still |
65 | /// using std::error_code. It will be removed in the future. |
66 | virtual std::error_code convertToErrorCode() const = 0; |
67 | |
68 | // Returns the class ID for this type. |
69 | static const void *classID() { return &ID; } |
70 | |
71 | // Returns the class ID for the dynamic type of this ErrorInfoBase instance. |
72 | virtual const void *dynamicClassID() const = 0; |
73 | |
74 | // Check whether this instance is a subclass of the class identified by |
75 | // ClassID. |
76 | virtual bool isA(const void *const ClassID) const { |
77 | return ClassID == classID(); |
78 | } |
79 | |
80 | // Check whether this instance is a subclass of ErrorInfoT. |
81 | template <typename ErrorInfoT> bool isA() const { |
82 | return isA(ErrorInfoT::classID()); |
83 | } |
84 | |
85 | private: |
86 | virtual void anchor(); |
87 | |
88 | static char ID; |
89 | }; |
90 | |
91 | /// Lightweight error class with error context and mandatory checking. |
92 | /// |
93 | /// Instances of this class wrap a ErrorInfoBase pointer. Failure states |
94 | /// are represented by setting the pointer to a ErrorInfoBase subclass |
95 | /// instance containing information describing the failure. Success is |
96 | /// represented by a null pointer value. |
97 | /// |
98 | /// Instances of Error also contains a 'Checked' flag, which must be set |
99 | /// before the destructor is called, otherwise the destructor will trigger a |
100 | /// runtime error. This enforces at runtime the requirement that all Error |
101 | /// instances be checked or returned to the caller. |
102 | /// |
103 | /// There are two ways to set the checked flag, depending on what state the |
104 | /// Error instance is in. For Error instances indicating success, it |
105 | /// is sufficient to invoke the boolean conversion operator. E.g.: |
106 | /// |
107 | /// @code{.cpp} |
108 | /// Error foo(<...>); |
109 | /// |
110 | /// if (auto E = foo(<...>)) |
111 | /// return E; // <- Return E if it is in the error state. |
112 | /// // We have verified that E was in the success state. It can now be safely |
113 | /// // destroyed. |
114 | /// @endcode |
115 | /// |
116 | /// A success value *can not* be dropped. For example, just calling 'foo(<...>)' |
117 | /// without testing the return value will raise a runtime error, even if foo |
118 | /// returns success. |
119 | /// |
120 | /// For Error instances representing failure, you must use either the |
121 | /// handleErrors or handleAllErrors function with a typed handler. E.g.: |
122 | /// |
123 | /// @code{.cpp} |
124 | /// class MyErrorInfo : public ErrorInfo<MyErrorInfo> { |
125 | /// // Custom error info. |
126 | /// }; |
127 | /// |
128 | /// Error foo(<...>) { return make_error<MyErrorInfo>(...); } |
129 | /// |
130 | /// auto E = foo(<...>); // <- foo returns failure with MyErrorInfo. |
131 | /// auto NewE = |
132 | /// handleErrors(E, |
133 | /// [](const MyErrorInfo &M) { |
134 | /// // Deal with the error. |
135 | /// }, |
136 | /// [](std::unique_ptr<OtherError> M) -> Error { |
137 | /// if (canHandle(*M)) { |
138 | /// // handle error. |
139 | /// return Error::success(); |
140 | /// } |
141 | /// // Couldn't handle this error instance. Pass it up the stack. |
142 | /// return Error(std::move(M)); |
143 | /// ); |
144 | /// // Note - we must check or return NewE in case any of the handlers |
145 | /// // returned a new error. |
146 | /// @endcode |
147 | /// |
148 | /// The handleAllErrors function is identical to handleErrors, except |
149 | /// that it has a void return type, and requires all errors to be handled and |
150 | /// no new errors be returned. It prevents errors (assuming they can all be |
151 | /// handled) from having to be bubbled all the way to the top-level. |
152 | /// |
153 | /// *All* Error instances must be checked before destruction, even if |
154 | /// they're moved-assigned or constructed from Success values that have already |
155 | /// been checked. This enforces checking through all levels of the call stack. |
156 | class LLVM_NODISCARD[[clang::warn_unused_result]] Error { |
157 | // ErrorList needs to be able to yank ErrorInfoBase pointers out of this |
158 | // class to add to the error list. |
159 | friend class ErrorList; |
160 | |
161 | // handleErrors needs to be able to set the Checked flag. |
162 | template <typename... HandlerTs> |
163 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
164 | |
165 | // Expected<T> needs to be able to steal the payload when constructed from an |
166 | // error. |
167 | template <typename T> friend class Expected; |
168 | |
169 | protected: |
170 | /// Create a success value. Prefer using 'Error::success()' for readability |
171 | Error() { |
172 | setPtr(nullptr); |
173 | setChecked(false); |
174 | } |
175 | |
176 | public: |
177 | /// Create a success value. |
178 | static ErrorSuccess success(); |
179 | |
180 | // Errors are not copy-constructable. |
181 | Error(const Error &Other) = delete; |
182 | |
183 | /// Move-construct an error value. The newly constructed error is considered |
184 | /// unchecked, even if the source error had been checked. The original error |
185 | /// becomes a checked Success value, regardless of its original state. |
186 | Error(Error &&Other) { |
187 | setChecked(true); |
188 | *this = std::move(Other); |
189 | } |
190 | |
191 | /// Create an error value. Prefer using the 'make_error' function, but |
192 | /// this constructor can be useful when "re-throwing" errors from handlers. |
193 | Error(std::unique_ptr<ErrorInfoBase> Payload) { |
194 | setPtr(Payload.release()); |
195 | setChecked(false); |
196 | } |
197 | |
198 | // Errors are not copy-assignable. |
199 | Error &operator=(const Error &Other) = delete; |
200 | |
201 | /// Move-assign an error value. The current error must represent success, you |
202 | /// you cannot overwrite an unhandled error. The current error is then |
203 | /// considered unchecked. The source error becomes a checked success value, |
204 | /// regardless of its original state. |
205 | Error &operator=(Error &&Other) { |
206 | // Don't allow overwriting of unchecked values. |
207 | assertIsChecked(); |
208 | setPtr(Other.getPtr()); |
209 | |
210 | // This Error is unchecked, even if the source error was checked. |
211 | setChecked(false); |
212 | |
213 | // Null out Other's payload and set its checked bit. |
214 | Other.setPtr(nullptr); |
215 | Other.setChecked(true); |
216 | |
217 | return *this; |
218 | } |
219 | |
220 | /// Destroy a Error. Fails with a call to abort() if the error is |
221 | /// unchecked. |
222 | ~Error() { |
223 | assertIsChecked(); |
224 | delete getPtr(); |
225 | } |
226 | |
227 | /// Bool conversion. Returns true if this Error is in a failure state, |
228 | /// and false if it is in an accept state. If the error is in a Success state |
229 | /// it will be considered checked. |
230 | explicit operator bool() { |
231 | setChecked(getPtr() == nullptr); |
232 | return getPtr() != nullptr; |
233 | } |
234 | |
235 | /// Check whether one error is a subclass of another. |
236 | template <typename ErrT> bool isA() const { |
237 | return getPtr() && getPtr()->isA(ErrT::classID()); |
238 | } |
239 | |
240 | /// Returns the dynamic class id of this error, or null if this is a success |
241 | /// value. |
242 | const void* dynamicClassID() const { |
243 | if (!getPtr()) |
244 | return nullptr; |
245 | return getPtr()->dynamicClassID(); |
246 | } |
247 | |
248 | private: |
249 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
250 | // assertIsChecked() happens very frequently, but under normal circumstances |
251 | // is supposed to be a no-op. So we want it to be inlined, but having a bunch |
252 | // of debug prints can cause the function to be too large for inlining. So |
253 | // it's important that we define this function out of line so that it can't be |
254 | // inlined. |
255 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
256 | void fatalUncheckedError() const; |
257 | #endif |
258 | |
259 | void assertIsChecked() { |
260 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
261 | if (LLVM_UNLIKELY(!getChecked() || getPtr())__builtin_expect((bool)(!getChecked() || getPtr()), false)) |
262 | fatalUncheckedError(); |
263 | #endif |
264 | } |
265 | |
266 | ErrorInfoBase *getPtr() const { |
267 | return reinterpret_cast<ErrorInfoBase*>( |
268 | reinterpret_cast<uintptr_t>(Payload) & |
269 | ~static_cast<uintptr_t>(0x1)); |
270 | } |
271 | |
272 | void setPtr(ErrorInfoBase *EI) { |
273 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
274 | Payload = reinterpret_cast<ErrorInfoBase*>( |
275 | (reinterpret_cast<uintptr_t>(EI) & |
276 | ~static_cast<uintptr_t>(0x1)) | |
277 | (reinterpret_cast<uintptr_t>(Payload) & 0x1)); |
278 | #else |
279 | Payload = EI; |
280 | #endif |
281 | } |
282 | |
283 | bool getChecked() const { |
284 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
285 | return (reinterpret_cast<uintptr_t>(Payload) & 0x1) == 0; |
286 | #else |
287 | return true; |
288 | #endif |
289 | } |
290 | |
291 | void setChecked(bool V) { |
292 | Payload = reinterpret_cast<ErrorInfoBase*>( |
293 | (reinterpret_cast<uintptr_t>(Payload) & |
294 | ~static_cast<uintptr_t>(0x1)) | |
295 | (V ? 0 : 1)); |
296 | } |
297 | |
298 | std::unique_ptr<ErrorInfoBase> takePayload() { |
299 | std::unique_ptr<ErrorInfoBase> Tmp(getPtr()); |
300 | setPtr(nullptr); |
301 | setChecked(true); |
302 | return Tmp; |
303 | } |
304 | |
305 | ErrorInfoBase *Payload = nullptr; |
306 | }; |
307 | |
308 | /// Subclass of Error for the sole purpose of identifying the success path in |
309 | /// the type system. This allows to catch invalid conversion to Expected<T> at |
310 | /// compile time. |
311 | class ErrorSuccess : public Error {}; |
312 | |
313 | inline ErrorSuccess Error::success() { return ErrorSuccess(); } |
314 | |
315 | /// Make a Error instance representing failure using the given error info |
316 | /// type. |
317 | template <typename ErrT, typename... ArgTs> Error make_error(ArgTs &&... Args) { |
318 | return Error(llvm::make_unique<ErrT>(std::forward<ArgTs>(Args)...)); |
319 | } |
320 | |
321 | /// Base class for user error types. Users should declare their error types |
322 | /// like: |
323 | /// |
324 | /// class MyError : public ErrorInfo<MyError> { |
325 | /// .... |
326 | /// }; |
327 | /// |
328 | /// This class provides an implementation of the ErrorInfoBase::kind |
329 | /// method, which is used by the Error RTTI system. |
330 | template <typename ThisErrT, typename ParentErrT = ErrorInfoBase> |
331 | class ErrorInfo : public ParentErrT { |
332 | public: |
333 | static const void *classID() { return &ThisErrT::ID; } |
334 | |
335 | const void *dynamicClassID() const override { return &ThisErrT::ID; } |
336 | |
337 | bool isA(const void *const ClassID) const override { |
338 | return ClassID == classID() || ParentErrT::isA(ClassID); |
339 | } |
340 | }; |
341 | |
342 | /// Special ErrorInfo subclass representing a list of ErrorInfos. |
343 | /// Instances of this class are constructed by joinError. |
344 | class ErrorList final : public ErrorInfo<ErrorList> { |
345 | // handleErrors needs to be able to iterate the payload list of an |
346 | // ErrorList. |
347 | template <typename... HandlerTs> |
348 | friend Error handleErrors(Error E, HandlerTs &&... Handlers); |
349 | |
350 | // joinErrors is implemented in terms of join. |
351 | friend Error joinErrors(Error, Error); |
352 | |
353 | public: |
354 | void log(raw_ostream &OS) const override { |
355 | OS << "Multiple errors:\n"; |
356 | for (auto &ErrPayload : Payloads) { |
357 | ErrPayload->log(OS); |
358 | OS << "\n"; |
359 | } |
360 | } |
361 | |
362 | std::error_code convertToErrorCode() const override; |
363 | |
364 | // Used by ErrorInfo::classID. |
365 | static char ID; |
366 | |
367 | private: |
368 | ErrorList(std::unique_ptr<ErrorInfoBase> Payload1, |
369 | std::unique_ptr<ErrorInfoBase> Payload2) { |
370 | assert(!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() &&(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)) |
371 | "ErrorList constructor payloads should be singleton errors")(static_cast <bool> (!Payload1->isA<ErrorList> () && !Payload2->isA<ErrorList>() && "ErrorList constructor payloads should be singleton errors") ? void (0) : __assert_fail ("!Payload1->isA<ErrorList>() && !Payload2->isA<ErrorList>() && \"ErrorList constructor payloads should be singleton errors\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 371, __extension__ __PRETTY_FUNCTION__)); |
372 | Payloads.push_back(std::move(Payload1)); |
373 | Payloads.push_back(std::move(Payload2)); |
374 | } |
375 | |
376 | static Error join(Error E1, Error E2) { |
377 | if (!E1) |
378 | return E2; |
379 | if (!E2) |
380 | return E1; |
381 | if (E1.isA<ErrorList>()) { |
382 | auto &E1List = static_cast<ErrorList &>(*E1.getPtr()); |
383 | if (E2.isA<ErrorList>()) { |
384 | auto E2Payload = E2.takePayload(); |
385 | auto &E2List = static_cast<ErrorList &>(*E2Payload); |
386 | for (auto &Payload : E2List.Payloads) |
387 | E1List.Payloads.push_back(std::move(Payload)); |
388 | } else |
389 | E1List.Payloads.push_back(E2.takePayload()); |
390 | |
391 | return E1; |
392 | } |
393 | if (E2.isA<ErrorList>()) { |
394 | auto &E2List = static_cast<ErrorList &>(*E2.getPtr()); |
395 | E2List.Payloads.insert(E2List.Payloads.begin(), E1.takePayload()); |
396 | return E2; |
397 | } |
398 | return Error(std::unique_ptr<ErrorList>( |
399 | new ErrorList(E1.takePayload(), E2.takePayload()))); |
400 | } |
401 | |
402 | std::vector<std::unique_ptr<ErrorInfoBase>> Payloads; |
403 | }; |
404 | |
405 | /// Concatenate errors. The resulting Error is unchecked, and contains the |
406 | /// ErrorInfo(s), if any, contained in E1, followed by the |
407 | /// ErrorInfo(s), if any, contained in E2. |
408 | inline Error joinErrors(Error E1, Error E2) { |
409 | return ErrorList::join(std::move(E1), std::move(E2)); |
410 | } |
411 | |
412 | /// Tagged union holding either a T or a Error. |
413 | /// |
414 | /// This class parallels ErrorOr, but replaces error_code with Error. Since |
415 | /// Error cannot be copied, this class replaces getError() with |
416 | /// takeError(). It also adds an bool errorIsA<ErrT>() method for testing the |
417 | /// error class type. |
418 | template <class T> class LLVM_NODISCARD[[clang::warn_unused_result]] Expected { |
419 | template <class T1> friend class ExpectedAsOutParameter; |
420 | template <class OtherT> friend class Expected; |
421 | |
422 | static const bool isRef = std::is_reference<T>::value; |
423 | |
424 | using wrap = ReferenceStorage<typename std::remove_reference<T>::type>; |
425 | |
426 | using error_type = std::unique_ptr<ErrorInfoBase>; |
427 | |
428 | public: |
429 | using storage_type = typename std::conditional<isRef, wrap, T>::type; |
430 | using value_type = T; |
431 | |
432 | private: |
433 | using reference = typename std::remove_reference<T>::type &; |
434 | using const_reference = const typename std::remove_reference<T>::type &; |
435 | using pointer = typename std::remove_reference<T>::type *; |
436 | using const_pointer = const typename std::remove_reference<T>::type *; |
437 | |
438 | public: |
439 | /// Create an Expected<T> error value from the given Error. |
440 | Expected(Error Err) |
441 | : HasError(true) |
442 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
443 | // Expected is unchecked upon construction in Debug builds. |
444 | , Unchecked(true) |
445 | #endif |
446 | { |
447 | assert(Err && "Cannot create Expected<T> from Error success value.")(static_cast <bool> (Err && "Cannot create Expected<T> from Error success value." ) ? void (0) : __assert_fail ("Err && \"Cannot create Expected<T> from Error success value.\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 447, __extension__ __PRETTY_FUNCTION__)); |
448 | new (getErrorStorage()) error_type(Err.takePayload()); |
449 | } |
450 | |
451 | /// Forbid to convert from Error::success() implicitly, this avoids having |
452 | /// Expected<T> foo() { return Error::success(); } which compiles otherwise |
453 | /// but triggers the assertion above. |
454 | Expected(ErrorSuccess) = delete; |
455 | |
456 | /// Create an Expected<T> success value from the given OtherT value, which |
457 | /// must be convertible to T. |
458 | template <typename OtherT> |
459 | Expected(OtherT &&Val, |
460 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
461 | * = nullptr) |
462 | : HasError(false) |
463 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
464 | // Expected is unchecked upon construction in Debug builds. |
465 | , Unchecked(true) |
466 | #endif |
467 | { |
468 | new (getStorage()) storage_type(std::forward<OtherT>(Val)); |
469 | } |
470 | |
471 | /// Move construct an Expected<T> value. |
472 | Expected(Expected &&Other) { moveConstruct(std::move(Other)); } |
473 | |
474 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
475 | /// must be convertible to T. |
476 | template <class OtherT> |
477 | Expected(Expected<OtherT> &&Other, |
478 | typename std::enable_if<std::is_convertible<OtherT, T>::value>::type |
479 | * = nullptr) { |
480 | moveConstruct(std::move(Other)); |
481 | } |
482 | |
483 | /// Move construct an Expected<T> value from an Expected<OtherT>, where OtherT |
484 | /// isn't convertible to T. |
485 | template <class OtherT> |
486 | explicit Expected( |
487 | Expected<OtherT> &&Other, |
488 | typename std::enable_if<!std::is_convertible<OtherT, T>::value>::type * = |
489 | nullptr) { |
490 | moveConstruct(std::move(Other)); |
491 | } |
492 | |
493 | /// Move-assign from another Expected<T>. |
494 | Expected &operator=(Expected &&Other) { |
495 | moveAssign(std::move(Other)); |
496 | return *this; |
497 | } |
498 | |
499 | /// Destroy an Expected<T>. |
500 | ~Expected() { |
501 | assertIsChecked(); |
502 | if (!HasError) |
503 | getStorage()->~storage_type(); |
504 | else |
505 | getErrorStorage()->~error_type(); |
506 | } |
507 | |
508 | /// \brief Return false if there is an error. |
509 | explicit operator bool() { |
510 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
511 | Unchecked = HasError; |
512 | #endif |
513 | return !HasError; |
514 | } |
515 | |
516 | /// \brief Returns a reference to the stored T value. |
517 | reference get() { |
518 | assertIsChecked(); |
519 | return *getStorage(); |
520 | } |
521 | |
522 | /// \brief Returns a const reference to the stored T value. |
523 | const_reference get() const { |
524 | assertIsChecked(); |
525 | return const_cast<Expected<T> *>(this)->get(); |
526 | } |
527 | |
528 | /// \brief Check that this Expected<T> is an error of type ErrT. |
529 | template <typename ErrT> bool errorIsA() const { |
530 | return HasError && (*getErrorStorage())->template isA<ErrT>(); |
531 | } |
532 | |
533 | /// \brief Take ownership of the stored error. |
534 | /// After calling this the Expected<T> is in an indeterminate state that can |
535 | /// only be safely destructed. No further calls (beside the destructor) should |
536 | /// be made on the Expected<T> vaule. |
537 | Error takeError() { |
538 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
539 | Unchecked = false; |
540 | #endif |
541 | return HasError ? Error(std::move(*getErrorStorage())) : Error::success(); |
542 | } |
543 | |
544 | /// \brief Returns a pointer to the stored T value. |
545 | pointer operator->() { |
546 | assertIsChecked(); |
547 | return toPointer(getStorage()); |
548 | } |
549 | |
550 | /// \brief Returns a const pointer to the stored T value. |
551 | const_pointer operator->() const { |
552 | assertIsChecked(); |
553 | return toPointer(getStorage()); |
554 | } |
555 | |
556 | /// \brief Returns a reference to the stored T value. |
557 | reference operator*() { |
558 | assertIsChecked(); |
559 | return *getStorage(); |
560 | } |
561 | |
562 | /// \brief Returns a const reference to the stored T value. |
563 | const_reference operator*() const { |
564 | assertIsChecked(); |
565 | return *getStorage(); |
566 | } |
567 | |
568 | private: |
569 | template <class T1> |
570 | static bool compareThisIfSameType(const T1 &a, const T1 &b) { |
571 | return &a == &b; |
572 | } |
573 | |
574 | template <class T1, class T2> |
575 | static bool compareThisIfSameType(const T1 &a, const T2 &b) { |
576 | return false; |
577 | } |
578 | |
579 | template <class OtherT> void moveConstruct(Expected<OtherT> &&Other) { |
580 | HasError = Other.HasError; |
581 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
582 | Unchecked = true; |
583 | Other.Unchecked = false; |
584 | #endif |
585 | |
586 | if (!HasError) |
587 | new (getStorage()) storage_type(std::move(*Other.getStorage())); |
588 | else |
589 | new (getErrorStorage()) error_type(std::move(*Other.getErrorStorage())); |
590 | } |
591 | |
592 | template <class OtherT> void moveAssign(Expected<OtherT> &&Other) { |
593 | assertIsChecked(); |
594 | |
595 | if (compareThisIfSameType(*this, Other)) |
596 | return; |
597 | |
598 | this->~Expected(); |
599 | new (this) Expected(std::move(Other)); |
600 | } |
601 | |
602 | pointer toPointer(pointer Val) { return Val; } |
603 | |
604 | const_pointer toPointer(const_pointer Val) const { return Val; } |
605 | |
606 | pointer toPointer(wrap *Val) { return &Val->get(); } |
607 | |
608 | const_pointer toPointer(const wrap *Val) const { return &Val->get(); } |
609 | |
610 | storage_type *getStorage() { |
611 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 611, __extension__ __PRETTY_FUNCTION__)); |
612 | return reinterpret_cast<storage_type *>(TStorage.buffer); |
613 | } |
614 | |
615 | const storage_type *getStorage() const { |
616 | assert(!HasError && "Cannot get value when an error exists!")(static_cast <bool> (!HasError && "Cannot get value when an error exists!" ) ? void (0) : __assert_fail ("!HasError && \"Cannot get value when an error exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 616, __extension__ __PRETTY_FUNCTION__)); |
617 | return reinterpret_cast<const storage_type *>(TStorage.buffer); |
618 | } |
619 | |
620 | error_type *getErrorStorage() { |
621 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 621, __extension__ __PRETTY_FUNCTION__)); |
622 | return reinterpret_cast<error_type *>(ErrorStorage.buffer); |
623 | } |
624 | |
625 | const error_type *getErrorStorage() const { |
626 | assert(HasError && "Cannot get error when a value exists!")(static_cast <bool> (HasError && "Cannot get error when a value exists!" ) ? void (0) : __assert_fail ("HasError && \"Cannot get error when a value exists!\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 626, __extension__ __PRETTY_FUNCTION__)); |
627 | return reinterpret_cast<const error_type *>(ErrorStorage.buffer); |
628 | } |
629 | |
630 | // Used by ExpectedAsOutParameter to reset the checked flag. |
631 | void setUnchecked() { |
632 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
633 | Unchecked = true; |
634 | #endif |
635 | } |
636 | |
637 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
638 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) |
639 | LLVM_ATTRIBUTE_NOINLINE__attribute__((noinline)) |
640 | void fatalUncheckedExpected() const { |
641 | dbgs() << "Expected<T> must be checked before access or destruction.\n"; |
642 | if (HasError) { |
643 | dbgs() << "Unchecked Expected<T> contained error:\n"; |
644 | (*getErrorStorage())->log(dbgs()); |
645 | } else |
646 | dbgs() << "Expected<T> value was in success state. (Note: Expected<T> " |
647 | "values in success mode must still be checked prior to being " |
648 | "destroyed).\n"; |
649 | abort(); |
650 | } |
651 | #endif |
652 | |
653 | void assertIsChecked() { |
654 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
655 | if (LLVM_UNLIKELY(Unchecked)__builtin_expect((bool)(Unchecked), false)) |
656 | fatalUncheckedExpected(); |
657 | #endif |
658 | } |
659 | |
660 | union { |
661 | AlignedCharArrayUnion<storage_type> TStorage; |
662 | AlignedCharArrayUnion<error_type> ErrorStorage; |
663 | }; |
664 | bool HasError : 1; |
665 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS1 |
666 | bool Unchecked : 1; |
667 | #endif |
668 | }; |
669 | |
670 | /// Report a serious error, calling any installed error handler. See |
671 | /// ErrorHandling.h. |
672 | LLVM_ATTRIBUTE_NORETURN__attribute__((noreturn)) void report_fatal_error(Error Err, |
673 | bool gen_crash_diag = true); |
674 | |
675 | /// Report a fatal error if Err is a failure value. |
676 | /// |
677 | /// This function can be used to wrap calls to fallible functions ONLY when it |
678 | /// is known that the Error will always be a success value. E.g. |
679 | /// |
680 | /// @code{.cpp} |
681 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
682 | /// // true. If DoFallibleOperation is false then foo always returns |
683 | /// // Error::success(). |
684 | /// Error foo(bool DoFallibleOperation); |
685 | /// |
686 | /// cantFail(foo(false)); |
687 | /// @endcode |
688 | inline void cantFail(Error Err, const char *Msg = nullptr) { |
689 | if (Err) { |
690 | if (!Msg) |
691 | Msg = "Failure value returned from cantFail wrapped call"; |
692 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 692); |
693 | } |
694 | } |
695 | |
696 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
697 | /// returns the contained value. |
698 | /// |
699 | /// This function can be used to wrap calls to fallible functions ONLY when it |
700 | /// is known that the Error will always be a success value. E.g. |
701 | /// |
702 | /// @code{.cpp} |
703 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
704 | /// // true. If DoFallibleOperation is false then foo always returns an int. |
705 | /// Expected<int> foo(bool DoFallibleOperation); |
706 | /// |
707 | /// int X = cantFail(foo(false)); |
708 | /// @endcode |
709 | template <typename T> |
710 | T cantFail(Expected<T> ValOrErr, const char *Msg = nullptr) { |
711 | if (ValOrErr) |
712 | return std::move(*ValOrErr); |
713 | else { |
714 | if (!Msg) |
715 | Msg = "Failure value returned from cantFail wrapped call"; |
716 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 716); |
717 | } |
718 | } |
719 | |
720 | /// Report a fatal error if ValOrErr is a failure value, otherwise unwraps and |
721 | /// returns the contained reference. |
722 | /// |
723 | /// This function can be used to wrap calls to fallible functions ONLY when it |
724 | /// is known that the Error will always be a success value. E.g. |
725 | /// |
726 | /// @code{.cpp} |
727 | /// // foo only attempts the fallible operation if DoFallibleOperation is |
728 | /// // true. If DoFallibleOperation is false then foo always returns a Bar&. |
729 | /// Expected<Bar&> foo(bool DoFallibleOperation); |
730 | /// |
731 | /// Bar &X = cantFail(foo(false)); |
732 | /// @endcode |
733 | template <typename T> |
734 | T& cantFail(Expected<T&> ValOrErr, const char *Msg = nullptr) { |
735 | if (ValOrErr) |
736 | return *ValOrErr; |
737 | else { |
738 | if (!Msg) |
739 | Msg = "Failure value returned from cantFail wrapped call"; |
740 | llvm_unreachable(Msg)::llvm::llvm_unreachable_internal(Msg, "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 740); |
741 | } |
742 | } |
743 | |
744 | /// Helper for testing applicability of, and applying, handlers for |
745 | /// ErrorInfo types. |
746 | template <typename HandlerT> |
747 | class ErrorHandlerTraits |
748 | : public ErrorHandlerTraits<decltype( |
749 | &std::remove_reference<HandlerT>::type::operator())> {}; |
750 | |
751 | // Specialization functions of the form 'Error (const ErrT&)'. |
752 | template <typename ErrT> class ErrorHandlerTraits<Error (&)(ErrT &)> { |
753 | public: |
754 | static bool appliesTo(const ErrorInfoBase &E) { |
755 | return E.template isA<ErrT>(); |
756 | } |
757 | |
758 | template <typename HandlerT> |
759 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
760 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 760, __extension__ __PRETTY_FUNCTION__)); |
761 | return H(static_cast<ErrT &>(*E)); |
762 | } |
763 | }; |
764 | |
765 | // Specialization functions of the form 'void (const ErrT&)'. |
766 | template <typename ErrT> class ErrorHandlerTraits<void (&)(ErrT &)> { |
767 | public: |
768 | static bool appliesTo(const ErrorInfoBase &E) { |
769 | return E.template isA<ErrT>(); |
770 | } |
771 | |
772 | template <typename HandlerT> |
773 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
774 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 774, __extension__ __PRETTY_FUNCTION__)); |
775 | H(static_cast<ErrT &>(*E)); |
776 | return Error::success(); |
777 | } |
778 | }; |
779 | |
780 | /// Specialization for functions of the form 'Error (std::unique_ptr<ErrT>)'. |
781 | template <typename ErrT> |
782 | class ErrorHandlerTraits<Error (&)(std::unique_ptr<ErrT>)> { |
783 | public: |
784 | static bool appliesTo(const ErrorInfoBase &E) { |
785 | return E.template isA<ErrT>(); |
786 | } |
787 | |
788 | template <typename HandlerT> |
789 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
790 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 790, __extension__ __PRETTY_FUNCTION__)); |
791 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
792 | return H(std::move(SubE)); |
793 | } |
794 | }; |
795 | |
796 | /// Specialization for functions of the form 'void (std::unique_ptr<ErrT>)'. |
797 | template <typename ErrT> |
798 | class ErrorHandlerTraits<void (&)(std::unique_ptr<ErrT>)> { |
799 | public: |
800 | static bool appliesTo(const ErrorInfoBase &E) { |
801 | return E.template isA<ErrT>(); |
802 | } |
803 | |
804 | template <typename HandlerT> |
805 | static Error apply(HandlerT &&H, std::unique_ptr<ErrorInfoBase> E) { |
806 | assert(appliesTo(*E) && "Applying incorrect handler")(static_cast <bool> (appliesTo(*E) && "Applying incorrect handler" ) ? void (0) : __assert_fail ("appliesTo(*E) && \"Applying incorrect handler\"" , "/build/llvm-toolchain-snapshot-7~svn326061/include/llvm/Support/Error.h" , 806, __extension__ __PRETTY_FUNCTION__)); |
807 | std::unique_ptr<ErrT> SubE(static_cast<ErrT *>(E.release())); |
808 | H(std::move(SubE)); |
809 | return Error::success(); |
810 | } |
811 | }; |
812 | |
813 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
814 | template <typename C, typename RetT, typename ErrT> |
815 | class ErrorHandlerTraits<RetT (C::*)(ErrT &)> |
816 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
817 | |
818 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
819 | template <typename C, typename RetT, typename ErrT> |
820 | class ErrorHandlerTraits<RetT (C::*)(ErrT &) const> |
821 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
822 | |
823 | // Specialization for member functions of the form 'RetT (const ErrT&)'. |
824 | template <typename C, typename RetT, typename ErrT> |
825 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &)> |
826 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
827 | |
828 | // Specialization for member functions of the form 'RetT (const ErrT&) const'. |
829 | template <typename C, typename RetT, typename ErrT> |
830 | class ErrorHandlerTraits<RetT (C::*)(const ErrT &) const> |
831 | : public ErrorHandlerTraits<RetT (&)(ErrT &)> {}; |
832 | |
833 | /// Specialization for member functions of the form |
834 | /// 'RetT (std::unique_ptr<ErrT>)'. |
835 | template <typename C, typename RetT, typename ErrT> |
836 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>)> |
837 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
838 | |
839 | /// Specialization for member functions of the form |
840 | /// 'RetT (std::unique_ptr<ErrT>) const'. |
841 | template <typename C, typename RetT, typename ErrT> |
842 | class ErrorHandlerTraits<RetT (C::*)(std::unique_ptr<ErrT>) const> |
843 | : public ErrorHandlerTraits<RetT (&)(std::unique_ptr<ErrT>)> {}; |
844 | |
845 | inline Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload) { |
846 | return Error(std::move(Payload)); |
847 | } |
848 | |
849 | template <typename HandlerT, typename... HandlerTs> |
850 | Error handleErrorImpl(std::unique_ptr<ErrorInfoBase> Payload, |
851 | HandlerT &&Handler, HandlerTs &&... Handlers) { |
852 | if (ErrorHandlerTraits<HandlerT>::appliesTo(*Payload)) |
853 | return ErrorHandlerTraits<HandlerT>::apply(std::forward<HandlerT>(Handler), |
854 | std::move(Payload)); |
855 | return handleErrorImpl(std::move(Payload), |
856 | std::forward<HandlerTs>(Handlers)...); |
857 | } |
858 | |
859 | /// Pass the ErrorInfo(s) contained in E to their respective handlers. Any |
860 | /// unhandled errors (or Errors returned by handlers) are re-concatenated and |
861 | /// returned. |
862 | /// Because this function returns an error, its result must also be checked |
863 | /// or returned. If you intend to handle all errors use handleAllErrors |
864 | /// (which returns void, and will abort() on unhandled errors) instead. |
865 | template <typename... HandlerTs> |
866 | Error handleErrors(Error E, HandlerTs &&... Hs) { |
867 | if (!E) |
868 | return Error::success(); |
869 | |
870 | std::unique_ptr<ErrorInfoBase> Payload = E.takePayload(); |
871 | |
872 | if (Payload->isA<ErrorList>()) { |
873 | ErrorList &List = static_cast<ErrorList &>(*Payload); |
874 | Error R; |
875 | for (auto &P : List.Payloads) |
876 | R = ErrorList::join( |
877 | std::move(R), |
878 | handleErrorImpl(std::move(P), std::forward<HandlerTs>(Hs)...)); |
879 | return R; |
880 | } |
881 | |
882 | return handleErrorImpl(std::move(Payload), std::forward<HandlerTs>(Hs)...); |
883 | } |
884 | |
885 | /// Behaves the same as handleErrors, except that it requires that all |
886 | /// errors be handled by the given handlers. If any unhandled error remains |
887 | /// after the handlers have run, report_fatal_error() will be called. |
888 | template <typename... HandlerTs> |
889 | void handleAllErrors(Error E, HandlerTs &&... Handlers) { |
890 | cantFail(handleErrors(std::move(E), std::forward<HandlerTs>(Handlers)...)); |
891 | } |
892 | |
893 | /// Check that E is a non-error, then drop it. |
894 | /// If E is an error report_fatal_error will be called. |
895 | inline void handleAllErrors(Error E) { |
896 | cantFail(std::move(E)); |
897 | } |
898 | |
899 | /// Handle any errors (if present) in an Expected<T>, then try a recovery path. |
900 | /// |
901 | /// If the incoming value is a success value it is returned unmodified. If it |
902 | /// is a failure value then it the contained error is passed to handleErrors. |
903 | /// If handleErrors is able to handle the error then the RecoveryPath functor |
904 | /// is called to supply the final result. If handleErrors is not able to |
905 | /// handle all errors then the unhandled errors are returned. |
906 | /// |
907 | /// This utility enables the follow pattern: |
908 | /// |
909 | /// @code{.cpp} |
910 | /// enum FooStrategy { Aggressive, Conservative }; |
911 | /// Expected<Foo> foo(FooStrategy S); |
912 | /// |
913 | /// auto ResultOrErr = |
914 | /// handleExpected( |
915 | /// foo(Aggressive), |
916 | /// []() { return foo(Conservative); }, |
917 | /// [](AggressiveStrategyError&) { |
918 | /// // Implicitly conusme this - we'll recover by using a conservative |
919 | /// // strategy. |
920 | /// }); |
921 | /// |
922 | /// @endcode |
923 | template <typename T, typename RecoveryFtor, typename... HandlerTs> |
924 | Expected<T> handleExpected(Expected<T> ValOrErr, RecoveryFtor &&RecoveryPath, |
925 | HandlerTs &&... Handlers) { |
926 | if (ValOrErr) |
927 | return ValOrErr; |
928 | |
929 | if (auto Err = handleErrors(ValOrErr.takeError(), |
930 | std::forward<HandlerTs>(Handlers)...)) |
931 | return std::move(Err); |
932 | |
933 | return RecoveryPath(); |
934 | } |
935 | |
936 | /// Log all errors (if any) in E to OS. If there are any errors, ErrorBanner |
937 | /// will be printed before the first one is logged. A newline will be printed |
938 | /// after each error. |
939 | /// |
940 | /// This is useful in the base level of your program to allow clean termination |
941 | /// (allowing clean deallocation of resources, etc.), while reporting error |
942 | /// information to the user. |
943 | void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner); |
944 | |
945 | /// Write all error messages (if any) in E to a string. The newline character |
946 | /// is used to separate error messages. |
947 | inline std::string toString(Error E) { |
948 | SmallVector<std::string, 2> Errors; |
949 | handleAllErrors(std::move(E), [&Errors](const ErrorInfoBase &EI) { |
950 | Errors.push_back(EI.message()); |
951 | }); |
952 | return join(Errors.begin(), Errors.end(), "\n"); |
953 | } |
954 | |
955 | /// Consume a Error without doing anything. This method should be used |
956 | /// only where an error can be considered a reasonable and expected return |
957 | /// value. |
958 | /// |
959 | /// Uses of this method are potentially indicative of design problems: If it's |
960 | /// legitimate to do nothing while processing an "error", the error-producer |
961 | /// might be more clearly refactored to return an Optional<T>. |
962 | inline void consumeError(Error Err) { |
963 | handleAllErrors(std::move(Err), [](const ErrorInfoBase &) {}); |
964 | } |
965 | |
966 | /// Helper for converting an Error to a bool. |
967 | /// |
968 | /// This method returns true if Err is in an error state, or false if it is |
969 | /// in a success state. Puts Err in a checked state in both cases (unlike |
970 | /// Error::operator bool(), which only does this for success states). |
971 | inline bool errorToBool(Error Err) { |
972 | bool IsError = static_cast<bool>(Err); |
973 | if (IsError) |
974 | consumeError(std::move(Err)); |
975 | return IsError; |
976 | } |
977 | |
978 | /// Helper for Errors used as out-parameters. |
979 | /// |
980 | /// This helper is for use with the Error-as-out-parameter idiom, where an error |
981 | /// is passed to a function or method by reference, rather than being returned. |
982 | /// In such cases it is helpful to set the checked bit on entry to the function |
983 | /// so that the error can be written to (unchecked Errors abort on assignment) |
984 | /// and clear the checked bit on exit so that clients cannot accidentally forget |
985 | /// to check the result. This helper performs these actions automatically using |
986 | /// RAII: |
987 | /// |
988 | /// @code{.cpp} |
989 | /// Result foo(Error &Err) { |
990 | /// ErrorAsOutParameter ErrAsOutParam(&Err); // 'Checked' flag set |
991 | /// // <body of foo> |
992 | /// // <- 'Checked' flag auto-cleared when ErrAsOutParam is destructed. |
993 | /// } |
994 | /// @endcode |
995 | /// |
996 | /// ErrorAsOutParameter takes an Error* rather than Error& so that it can be |
997 | /// used with optional Errors (Error pointers that are allowed to be null). If |
998 | /// ErrorAsOutParameter took an Error reference, an instance would have to be |
999 | /// created inside every condition that verified that Error was non-null. By |
1000 | /// taking an Error pointer we can just create one instance at the top of the |
1001 | /// function. |
1002 | class ErrorAsOutParameter { |
1003 | public: |
1004 | ErrorAsOutParameter(Error *Err) : Err(Err) { |
1005 | // Raise the checked bit if Err is success. |
1006 | if (Err) |
1007 | (void)!!*Err; |
1008 | } |
1009 | |
1010 | ~ErrorAsOutParameter() { |
1011 | // Clear the checked bit. |
1012 | if (Err && !*Err) |
1013 | *Err = Error::success(); |
1014 | } |
1015 | |
1016 | private: |
1017 | Error *Err; |
1018 | }; |
1019 | |
1020 | /// Helper for Expected<T>s used as out-parameters. |
1021 | /// |
1022 | /// See ErrorAsOutParameter. |
1023 | template <typename T> |
1024 | class ExpectedAsOutParameter { |
1025 | public: |
1026 | ExpectedAsOutParameter(Expected<T> *ValOrErr) |
1027 | : ValOrErr(ValOrErr) { |
1028 | if (ValOrErr) |
1029 | (void)!!*ValOrErr; |
1030 | } |
1031 | |
1032 | ~ExpectedAsOutParameter() { |
1033 | if (ValOrErr) |
1034 | ValOrErr->setUnchecked(); |
1035 | } |
1036 | |
1037 | private: |
1038 | Expected<T> *ValOrErr; |
1039 | }; |
1040 | |
1041 | /// This class wraps a std::error_code in a Error. |
1042 | /// |
1043 | /// This is useful if you're writing an interface that returns a Error |
1044 | /// (or Expected) and you want to call code that still returns |
1045 | /// std::error_codes. |
1046 | class ECError : public ErrorInfo<ECError> { |
1047 | friend Error errorCodeToError(std::error_code); |
1048 | |
1049 | public: |
1050 | void setErrorCode(std::error_code EC) { this->EC = EC; } |
1051 | std::error_code convertToErrorCode() const override { return EC; } |
1052 | void log(raw_ostream &OS) const override { OS << EC.message(); } |
1053 | |
1054 | // Used by ErrorInfo::classID. |
1055 | static char ID; |
1056 | |
1057 | protected: |
1058 | ECError() = default; |
1059 | ECError(std::error_code EC) : EC(EC) {} |
1060 | |
1061 | std::error_code EC; |
1062 | }; |
1063 | |
1064 | /// The value returned by this function can be returned from convertToErrorCode |
1065 | /// for Error values where no sensible translation to std::error_code exists. |
1066 | /// It should only be used in this situation, and should never be used where a |
1067 | /// sensible conversion to std::error_code is available, as attempts to convert |
1068 | /// to/from this error will result in a fatal error. (i.e. it is a programmatic |
1069 | ///error to try to convert such a value). |
1070 | std::error_code inconvertibleErrorCode(); |
1071 | |
1072 | /// Helper for converting an std::error_code to a Error. |
1073 | Error errorCodeToError(std::error_code EC); |
1074 | |
1075 | /// Helper for converting an ECError to a std::error_code. |
1076 | /// |
1077 | /// This method requires that Err be Error() or an ECError, otherwise it |
1078 | /// will trigger a call to abort(). |
1079 | std::error_code errorToErrorCode(Error Err); |
1080 | |
1081 | /// Convert an ErrorOr<T> to an Expected<T>. |
1082 | template <typename T> Expected<T> errorOrToExpected(ErrorOr<T> &&EO) { |
1083 | if (auto EC = EO.getError()) |
1084 | return errorCodeToError(EC); |
1085 | return std::move(*EO); |
1086 | } |
1087 | |
1088 | /// Convert an Expected<T> to an ErrorOr<T>. |
1089 | template <typename T> ErrorOr<T> expectedToErrorOr(Expected<T> &&E) { |
1090 | if (auto Err = E.takeError()) |
1091 | return errorToErrorCode(std::move(Err)); |
1092 | return std::move(*E); |
1093 | } |
1094 | |
1095 | /// This class wraps a string in an Error. |
1096 | /// |
1097 | /// StringError is useful in cases where the client is not expected to be able |
1098 | /// to consume the specific error message programmatically (for example, if the |
1099 | /// error message is to be presented to the user). |
1100 | class StringError : public ErrorInfo<StringError> { |
1101 | public: |
1102 | static char ID; |
1103 | |
1104 | StringError(const Twine &S, std::error_code EC); |
1105 | |
1106 | void log(raw_ostream &OS) const override; |
1107 | std::error_code convertToErrorCode() const override; |
1108 | |
1109 | const std::string &getMessage() const { return Msg; } |
1110 | |
1111 | private: |
1112 | std::string Msg; |
1113 | std::error_code EC; |
1114 | }; |
1115 | |
1116 | /// Helper for check-and-exit error handling. |
1117 | /// |
1118 | /// For tool use only. NOT FOR USE IN LIBRARY CODE. |
1119 | /// |
1120 | class ExitOnError { |
1121 | public: |
1122 | /// Create an error on exit helper. |
1123 | ExitOnError(std::string Banner = "", int DefaultErrorExitCode = 1) |
1124 | : Banner(std::move(Banner)), |
1125 | GetExitCode([=](const Error &) { return DefaultErrorExitCode; }) {} |
1126 | |
1127 | /// Set the banner string for any errors caught by operator(). |
1128 | void setBanner(std::string Banner) { this->Banner = std::move(Banner); } |
1129 | |
1130 | /// Set the exit-code mapper function. |
1131 | void setExitCodeMapper(std::function<int(const Error &)> GetExitCode) { |
1132 | this->GetExitCode = std::move(GetExitCode); |
1133 | } |
1134 | |
1135 | /// Check Err. If it's in a failure state log the error(s) and exit. |
1136 | void operator()(Error Err) const { checkError(std::move(Err)); } |
1137 | |
1138 | /// Check E. If it's in a success state then return the contained value. If |
1139 | /// it's in a failure state log the error(s) and exit. |
1140 | template <typename T> T operator()(Expected<T> &&E) const { |
1141 | checkError(E.takeError()); |
1142 | return std::move(*E); |
1143 | } |
1144 | |
1145 | /// Check E. If it's in a success state then return the contained reference. If |
1146 | /// it's in a failure state log the error(s) and exit. |
1147 | template <typename T> T& operator()(Expected<T&> &&E) const { |
1148 | checkError(E.takeError()); |
1149 | return *E; |
1150 | } |
1151 | |
1152 | private: |
1153 | void checkError(Error Err) const { |
1154 | if (Err) { |
1155 | int ExitCode = GetExitCode(Err); |
1156 | logAllUnhandledErrors(std::move(Err), errs(), Banner); |
1157 | exit(ExitCode); |
1158 | } |
1159 | } |
1160 | |
1161 | std::string Banner; |
1162 | std::function<int(const Error &)> GetExitCode; |
1163 | }; |
1164 | |
1165 | } // end namespace llvm |
1166 | |
1167 | #endif // LLVM_SUPPORT_ERROR_H |