Mercurial > hg > sv-dependency-builds
comparison osx/include/kj/debug.h @ 62:0994c39f1e94
Cap'n Proto v0.6 + build for OSX
author | Chris Cannam <cannam@all-day-breakfast.com> |
---|---|
date | Mon, 22 May 2017 10:01:37 +0100 |
parents | 3ab5a40c4e3b |
children |
comparison
equal
deleted
inserted
replaced
61:d101c4099725 | 62:0994c39f1e94 |
---|---|
163 | 163 |
164 #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ | 164 #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ |
165 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | 165 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ |
166 errorNumber, code, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | 166 errorNumber, code, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) |
167 | 167 |
168 #if _WIN32 | |
169 | |
170 #define KJ_WIN32(call, ...) \ | |
171 if (::kj::_::Debug::isWin32Success(call)) {} else \ | |
172 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
173 ::kj::_::Debug::getWin32Error(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | |
174 | |
175 #define KJ_WINSOCK(call, ...) \ | |
176 if ((call) != SOCKET_ERROR) {} else \ | |
177 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
178 ::kj::_::Debug::getWin32Error(), #call, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | |
179 | |
180 #define KJ_FAIL_WIN32(code, errorNumber, ...) \ | |
181 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
182 ::kj::_::Debug::Win32Error(errorNumber), code, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | |
183 | |
184 #endif | |
185 | |
168 #define KJ_UNIMPLEMENTED(...) \ | 186 #define KJ_UNIMPLEMENTED(...) \ |
169 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \ | 187 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \ |
170 nullptr, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) | 188 nullptr, "" #__VA_ARGS__, __VA_ARGS__);; f.fatal()) |
171 | 189 |
190 // TODO(msvc): MSVC mis-deduces `ContextImpl<decltype(func)>` as `ContextImpl<int>` in some edge | |
191 // cases, such as inside nested lambdas inside member functions. Wrapping the type in | |
192 // `decltype(instance<...>())` helps it deduce the context function's type correctly. | |
172 #define KJ_CONTEXT(...) \ | 193 #define KJ_CONTEXT(...) \ |
173 auto KJ_UNIQUE_NAME(_kjContextFunc) = [&]() -> ::kj::_::Debug::Context::Value { \ | 194 auto KJ_UNIQUE_NAME(_kjContextFunc) = [&]() -> ::kj::_::Debug::Context::Value { \ |
174 return ::kj::_::Debug::Context::Value(__FILE__, __LINE__, \ | 195 return ::kj::_::Debug::Context::Value(__FILE__, __LINE__, \ |
175 ::kj::_::Debug::makeDescription("" #__VA_ARGS__, __VA_ARGS__)); \ | 196 ::kj::_::Debug::makeDescription("" #__VA_ARGS__, __VA_ARGS__)); \ |
176 }; \ | 197 }; \ |
177 ::kj::_::Debug::ContextImpl<decltype(KJ_UNIQUE_NAME(_kjContextFunc))> \ | 198 decltype(::kj::instance<::kj::_::Debug::ContextImpl<decltype(KJ_UNIQUE_NAME(_kjContextFunc))>>()) \ |
178 KJ_UNIQUE_NAME(_kjContext)(KJ_UNIQUE_NAME(_kjContextFunc)) | 199 KJ_UNIQUE_NAME(_kjContext)(KJ_UNIQUE_NAME(_kjContextFunc)) |
179 | 200 |
180 #define KJ_REQUIRE_NONNULL(value, ...) \ | 201 #define KJ_REQUIRE_NONNULL(value, ...) \ |
181 (*[&] { \ | 202 (*[&] { \ |
182 auto _kj_result = ::kj::_::readMaybe(value); \ | 203 auto _kj_result = ::kj::_::readMaybe(value); \ |
221 | 242 |
222 #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ | 243 #define KJ_FAIL_SYSCALL(code, errorNumber, ...) \ |
223 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | 244 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ |
224 errorNumber, code, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | 245 errorNumber, code, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) |
225 | 246 |
247 #if _WIN32 | |
248 | |
249 #define KJ_WIN32(call, ...) \ | |
250 if (::kj::_::Debug::isWin32Success(call)) {} else \ | |
251 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
252 ::kj::_::Debug::getWin32Error(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | |
253 | |
254 #define KJ_WINSOCK(call, ...) \ | |
255 if ((call) != SOCKET_ERROR) {} else \ | |
256 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
257 ::kj::_::Debug::getWin32Error(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | |
258 | |
259 #define KJ_FAIL_WIN32(code, errorNumber, ...) \ | |
260 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, \ | |
261 ::kj::_::Debug::Win32Error(errorNumber), code, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | |
262 | |
263 #endif | |
264 | |
226 #define KJ_UNIMPLEMENTED(...) \ | 265 #define KJ_UNIMPLEMENTED(...) \ |
227 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \ | 266 for (::kj::_::Debug::Fault f(__FILE__, __LINE__, ::kj::Exception::Type::UNIMPLEMENTED, \ |
228 nullptr, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) | 267 nullptr, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal()) |
229 | 268 |
230 #define KJ_CONTEXT(...) \ | 269 #define KJ_CONTEXT(...) \ |
249 ::kj::Exception(::kj::Exception::Type::type, __FILE__, __LINE__, \ | 288 ::kj::Exception(::kj::Exception::Type::type, __FILE__, __LINE__, \ |
250 ::kj::_::Debug::makeDescription(#__VA_ARGS__, ##__VA_ARGS__)) | 289 ::kj::_::Debug::makeDescription(#__VA_ARGS__, ##__VA_ARGS__)) |
251 | 290 |
252 #endif | 291 #endif |
253 | 292 |
293 #define KJ_SYSCALL_HANDLE_ERRORS(call) \ | |
294 if (int _kjSyscallError = ::kj::_::Debug::syscallError([&](){return (call);}, false)) \ | |
295 switch (int error = _kjSyscallError) | |
296 // Like KJ_SYSCALL, but doesn't throw. Instead, the block after the macro is a switch block on the | |
297 // error. Additionally, the int value `error` is defined within the block. So you can do: | |
298 // | |
299 // KJ_SYSCALL_HANDLE_ERRORS(foo()) { | |
300 // case ENOENT: | |
301 // handleNoSuchFile(); | |
302 // break; | |
303 // case EEXIST: | |
304 // handleExists(); | |
305 // break; | |
306 // default: | |
307 // KJ_FAIL_SYSCALL("foo()", error); | |
308 // } else { | |
309 // handleSuccessCase(); | |
310 // } | |
311 | |
254 #define KJ_ASSERT KJ_REQUIRE | 312 #define KJ_ASSERT KJ_REQUIRE |
255 #define KJ_FAIL_ASSERT KJ_FAIL_REQUIRE | 313 #define KJ_FAIL_ASSERT KJ_FAIL_REQUIRE |
256 #define KJ_ASSERT_NONNULL KJ_REQUIRE_NONNULL | 314 #define KJ_ASSERT_NONNULL KJ_REQUIRE_NONNULL |
257 // Use "ASSERT" in place of "REQUIRE" when the problem is local to the immediate surrounding code. | 315 // Use "ASSERT" in place of "REQUIRE" when the problem is local to the immediate surrounding code. |
258 // That is, if the assert ever fails, it indicates that the immediate surrounding code is broken. | 316 // That is, if the assert ever fails, it indicates that the immediate surrounding code is broken. |
273 public: | 331 public: |
274 Debug() = delete; | 332 Debug() = delete; |
275 | 333 |
276 typedef LogSeverity Severity; // backwards-compatibility | 334 typedef LogSeverity Severity; // backwards-compatibility |
277 | 335 |
336 #if _WIN32 | |
337 struct Win32Error { | |
338 // Hack for overloading purposes. | |
339 uint number; | |
340 inline explicit Win32Error(uint number): number(number) {} | |
341 }; | |
342 #endif | |
343 | |
278 static inline bool shouldLog(LogSeverity severity) { return severity >= minSeverity; } | 344 static inline bool shouldLog(LogSeverity severity) { return severity >= minSeverity; } |
279 // Returns whether messages of the given severity should be logged. | 345 // Returns whether messages of the given severity should be logged. |
280 | 346 |
281 static inline void setLogLevel(LogSeverity severity) { minSeverity = severity; } | 347 static inline void setLogLevel(LogSeverity severity) { minSeverity = severity; } |
282 // Set the minimum message severity which will be logged. | 348 // Set the minimum message severity which will be logged. |
287 static void log(const char* file, int line, LogSeverity severity, const char* macroArgs, | 353 static void log(const char* file, int line, LogSeverity severity, const char* macroArgs, |
288 Params&&... params); | 354 Params&&... params); |
289 | 355 |
290 class Fault { | 356 class Fault { |
291 public: | 357 public: |
292 template <typename... Params> | 358 template <typename Code, typename... Params> |
293 Fault(const char* file, int line, Exception::Type type, | 359 Fault(const char* file, int line, Code code, |
294 const char* condition, const char* macroArgs, Params&&... params); | |
295 template <typename... Params> | |
296 Fault(const char* file, int line, int osErrorNumber, | |
297 const char* condition, const char* macroArgs, Params&&... params); | 360 const char* condition, const char* macroArgs, Params&&... params); |
298 Fault(const char* file, int line, Exception::Type type, | 361 Fault(const char* file, int line, Exception::Type type, |
299 const char* condition, const char* macroArgs); | 362 const char* condition, const char* macroArgs); |
300 Fault(const char* file, int line, int osErrorNumber, | 363 Fault(const char* file, int line, int osErrorNumber, |
301 const char* condition, const char* macroArgs); | 364 const char* condition, const char* macroArgs); |
365 #if _WIN32 | |
366 Fault(const char* file, int line, Win32Error osErrorNumber, | |
367 const char* condition, const char* macroArgs); | |
368 #endif | |
302 ~Fault() noexcept(false); | 369 ~Fault() noexcept(false); |
303 | 370 |
304 KJ_NOINLINE KJ_NORETURN(void fatal()); | 371 KJ_NOINLINE KJ_NORETURN(void fatal()); |
305 // Throw the exception. | 372 // Throw the exception. |
306 | 373 |
307 private: | 374 private: |
308 void init(const char* file, int line, Exception::Type type, | 375 void init(const char* file, int line, Exception::Type type, |
309 const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | 376 const char* condition, const char* macroArgs, ArrayPtr<String> argValues); |
310 void init(const char* file, int line, int osErrorNumber, | 377 void init(const char* file, int line, int osErrorNumber, |
311 const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | 378 const char* condition, const char* macroArgs, ArrayPtr<String> argValues); |
379 #if _WIN32 | |
380 void init(const char* file, int line, Win32Error osErrorNumber, | |
381 const char* condition, const char* macroArgs, ArrayPtr<String> argValues); | |
382 #endif | |
312 | 383 |
313 Exception* exception; | 384 Exception* exception; |
314 }; | 385 }; |
315 | 386 |
316 class SyscallResult { | 387 class SyscallResult { |
323 int errorNumber; | 394 int errorNumber; |
324 }; | 395 }; |
325 | 396 |
326 template <typename Call> | 397 template <typename Call> |
327 static SyscallResult syscall(Call&& call, bool nonblocking); | 398 static SyscallResult syscall(Call&& call, bool nonblocking); |
399 template <typename Call> | |
400 static int syscallError(Call&& call, bool nonblocking); | |
401 | |
402 #if _WIN32 | |
403 static bool isWin32Success(int boolean); | |
404 static bool isWin32Success(void* handle); | |
405 static Win32Error getWin32Error(); | |
406 #endif | |
328 | 407 |
329 class Context: public ExceptionCallback { | 408 class Context: public ExceptionCallback { |
330 public: | 409 public: |
331 Context(); | 410 Context(); |
332 KJ_DISALLOW_COPY(Context); | 411 KJ_DISALLOW_COPY(Context); |
392 template <> | 471 template <> |
393 inline void Debug::log<>(const char* file, int line, LogSeverity severity, const char* macroArgs) { | 472 inline void Debug::log<>(const char* file, int line, LogSeverity severity, const char* macroArgs) { |
394 logInternal(file, line, severity, macroArgs, nullptr); | 473 logInternal(file, line, severity, macroArgs, nullptr); |
395 } | 474 } |
396 | 475 |
397 template <typename... Params> | 476 template <typename Code, typename... Params> |
398 Debug::Fault::Fault(const char* file, int line, Exception::Type type, | 477 Debug::Fault::Fault(const char* file, int line, Code code, |
399 const char* condition, const char* macroArgs, Params&&... params) | 478 const char* condition, const char* macroArgs, Params&&... params) |
400 : exception(nullptr) { | 479 : exception(nullptr) { |
401 String argValues[sizeof...(Params)] = {str(params)...}; | 480 String argValues[sizeof...(Params)] = {str(params)...}; |
402 init(file, line, type, condition, macroArgs, | 481 init(file, line, code, condition, macroArgs, |
403 arrayPtr(argValues, sizeof...(Params))); | |
404 } | |
405 | |
406 template <typename... Params> | |
407 Debug::Fault::Fault(const char* file, int line, int osErrorNumber, | |
408 const char* condition, const char* macroArgs, Params&&... params) | |
409 : exception(nullptr) { | |
410 String argValues[sizeof...(Params)] = {str(params)...}; | |
411 init(file, line, osErrorNumber, condition, macroArgs, | |
412 arrayPtr(argValues, sizeof...(Params))); | 482 arrayPtr(argValues, sizeof...(Params))); |
413 } | 483 } |
414 | 484 |
415 inline Debug::Fault::Fault(const char* file, int line, int osErrorNumber, | 485 inline Debug::Fault::Fault(const char* file, int line, int osErrorNumber, |
416 const char* condition, const char* macroArgs) | 486 const char* condition, const char* macroArgs) |
421 inline Debug::Fault::Fault(const char* file, int line, kj::Exception::Type type, | 491 inline Debug::Fault::Fault(const char* file, int line, kj::Exception::Type type, |
422 const char* condition, const char* macroArgs) | 492 const char* condition, const char* macroArgs) |
423 : exception(nullptr) { | 493 : exception(nullptr) { |
424 init(file, line, type, condition, macroArgs, nullptr); | 494 init(file, line, type, condition, macroArgs, nullptr); |
425 } | 495 } |
496 | |
497 #if _WIN32 | |
498 inline Debug::Fault::Fault(const char* file, int line, Win32Error osErrorNumber, | |
499 const char* condition, const char* macroArgs) | |
500 : exception(nullptr) { | |
501 init(file, line, osErrorNumber, condition, macroArgs, nullptr); | |
502 } | |
503 | |
504 inline bool Debug::isWin32Success(int boolean) { | |
505 return boolean; | |
506 } | |
507 inline bool Debug::isWin32Success(void* handle) { | |
508 // Assume null and INVALID_HANDLE_VALUE mean failure. | |
509 return handle != nullptr && handle != (void*)-1; | |
510 } | |
511 #endif | |
426 | 512 |
427 template <typename Call> | 513 template <typename Call> |
428 Debug::SyscallResult Debug::syscall(Call&& call, bool nonblocking) { | 514 Debug::SyscallResult Debug::syscall(Call&& call, bool nonblocking) { |
429 while (call() < 0) { | 515 while (call() < 0) { |
430 int errorNum = getOsErrorNumber(nonblocking); | 516 int errorNum = getOsErrorNumber(nonblocking); |
436 } | 522 } |
437 } | 523 } |
438 return SyscallResult(0); | 524 return SyscallResult(0); |
439 } | 525 } |
440 | 526 |
527 template <typename Call> | |
528 int Debug::syscallError(Call&& call, bool nonblocking) { | |
529 while (call() < 0) { | |
530 int errorNum = getOsErrorNumber(nonblocking); | |
531 // getOsErrorNumber() returns -1 to indicate EINTR. | |
532 // Also, if nonblocking is true, then it returns 0 on EAGAIN, which will then be treated as a | |
533 // non-error. | |
534 if (errorNum != -1) { | |
535 return errorNum; | |
536 } | |
537 } | |
538 return 0; | |
539 } | |
540 | |
441 template <typename... Params> | 541 template <typename... Params> |
442 String Debug::makeDescription(const char* macroArgs, Params&&... params) { | 542 String Debug::makeDescription(const char* macroArgs, Params&&... params) { |
443 String argValues[sizeof...(Params)] = {str(params)...}; | 543 String argValues[sizeof...(Params)] = {str(params)...}; |
444 return makeDescriptionInternal(macroArgs, arrayPtr(argValues, sizeof...(Params))); | 544 return makeDescriptionInternal(macroArgs, arrayPtr(argValues, sizeof...(Params))); |
445 } | 545 } |