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 }