// Copyright 2007 Georgia Institute of Technology. All rights reserved. /** * @file common.h * * The bare necessities of FASTlib programming in C, including * standard types, formatted messages to stderr, and useful libraries * and compiler directives. * * This file should be included before all built-in libraries because * it includes the _REENTRANT definition needed for thread-safety. * Files base.h or fastlib.h include this file first and may serve as * surrogates. * * @see compiler.h */ #ifndef BASE_COMMON_H #define BASE_COMMON_H #ifndef _REENTRANT #define _REENTRANT #endif #include "base/basic_types.h" #include "compiler.h" #include "ansi_colors.h" #include #include #include #include #include EXTERN_C_BEGIN /** A no-op used in some macros. */ #define NOP ((void)0) /* Types and definitions to assist managment of problem scale. */ /* Ensure that one and only one problem scale is selected. */ #if defined(SCALE_MASSIVE) #if defined(SCALE_LARGE) || defined(SCALE_NORMAL) #error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined. #endif #elif defined(SCALE_LARGE) #if defined(SCALE_NORMAL) #error Only one of SCALE_MASSIVE, SCALE_LARGE, or SCALE_NORMAL may be defined. #endif #elif !defined(SCALE_NORMAL) #define SCALE_NORMAL #endif /** * Index type used in FASTlib for array sizes, etc. * * Define one of the following (default SCALE_NORMAL): * * SCALE_NORMAL - Problems are as large can be indexed with your * machine's standard integers. As of 2007, this is 32 bits. * * SCALE_LARGE - Problems are as large as your machine's architecture * can support. Unless you have more than 2 billion data points, * this will waste some space and reduce cache efficiency. * * SCALE_MASSIVE - Problems are 64-bit indexed even on 32-bit * machines, rendering them larger than RAM. * * Values are signed to allow uninitialized indices of -1 as well as * consideration of potentially negative differences between indices. */ #if defined(SCALE_MASSIVE) typedef int64 index_t; /* For larger than RAM data sets. */ #elif defined(SCALE_LARGE) typedef ssize_t index_t; /* As large as this machine can handle. */ #elif defined(SCALE_NORMAL) typedef int index_t; /* Normal sized data; usually 32-bit. */ #endif /** * Length modifier for emitting index_t with printf. * * Example: * @code * index_t i = 42; * printf("%"LI"d\n", i); * @endcode */ #if defined(SCALE_MASSIVE) #define LI L64 #elif defined(SCALE_LARGE) #define LI "l" /* TODO: confirm correct. */ #elif defined(SCALE_NORMAL) #define LI "" #endif /** Size of a kilobyte in bytes. */ #define KILOBYTE (((size_t)1) << 10) /** Size of a megabyte in bytes. */ #define MEGABYTE (((size_t)1) << 20) /** Size of a gigabyte in bytes. */ #define GIGABYTE (((size_t)1) << 30) /* Add more of these as necessary. */ /* Tools for FASTlib stderr messages, warnings, and errors. */ /** Whether to segfault instead of calling C's abort(). */ extern int segfault_on_abort; /** Whether to treat nonfatal warnings as fatal. */ extern int abort_on_nonfatal; /** Whether to wait for user input after nonfatal warnings. */ extern int pause_on_nonfatal; /** Whether to print call locations for notifications. */ extern int print_notify_locs; /** Different types of messages FASTlib prints to stderr. */ typedef enum { /** Message for an unrecoverable error. */ FL_MSG_FATAL = 0, /** Message for a potentially recoverable warning. */ FL_MSG_NONFATAL = 1, /** Message for a significant but non-problematic event. */ FL_MSG_NOTIFY_STAR = 2, /** Message for a standard, non-problematic event. */ FL_MSG_NOTIFY = 3 } fl_msg_t; /** Default markers for FASTlib messages. */ extern char fl_msg_marker[]; /** Default colors for FASTlib message markers. */ extern const char * fl_msg_color[]; /** * Terminates with an error, flushing all streams. * * Behavior adjustable with segfault_on_abort, which may be handy for * valgrind or other debuggers. */ COMPILER_NO_RETURN void fl_abort(void); /** * Waits for the user to press return. * * This function will obliterate anything in the stdin buffer. */ void fl_pause(void); /** Prints a colored message header. */ void fl_print_msg_header(char marker, const char *color); /** Print a location in code. */ void fl_print_msg_loc(const char *file, const char *func, int line); /** Implementation for FATAL. */ COMPILER_NO_RETURN COMPILER_PRINTF(4, 5) void fl_print_fatal_msg(const char *file, const char *func, int line, const char* format, ...); /** Implementation for NONFATAL, NOTIFY_STAR, and NOTIFY. */ COMPILER_PRINTF(5, 6) void fl_print_msg(const char *file, const char *func, int line, fl_msg_t msg_type, const char* format, ...); /** * Aborts, printing call location and a message to stderr. * * @param msg_params format string and variables, as in printf */ #define FATAL(msg_params...) (fl_print_fatal_msg( \ __FILE__, __FUNCTION__, __LINE__, msg_params)) /** * (Possibly) aborts or pauses, printing call location and a message * to stderr. * * @param msg_params format string and variables, as in printf */ #define NONFATAL(msg_params...) (fl_print_msg( \ __FILE__, __FUNCTION__, __LINE__, FL_MSG_NONFATAL, msg_params)) /** * Prints (possibly) call location and a message with special marker * to stderr. * * @param msg_params format string and variables, as in printf */ #define NOTIFY_STAR(msg_params...) (fl_print_msg( \ __FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY_STAR, msg_params)) /** * Prints (possibly) call location and a message with standard marker * to stderr. * * @param msg_params format string and variables, as in printf */ #define NOTIFY(msg_params...) (fl_print_msg( \ __FILE__, __FUNCTION__, __LINE__, FL_MSG_NOTIFY, msg_params)) /** * Prints a progress bar using ANSI commands to stay in place. * * For proper formatting, desc should be 22 characters or fewer and * the program should avoid output of other text while emitting a * progress bar. When finished with a progress bar, emit a newline * ('\n') to keep the bar on screen or a line of spaces followed by a * carriage return ('\r') to clear it. * * @param name printed next to the progress bar; max 22 characters * @param perc percentage of bar filled; should range from 0 to 100 */ void fl_print_progress(const char *name, int perc); /* Tools for expressing success or failure of FASTlib functions. */ /** * Type for indicating success or failure. * * Return these rather than ints to indicate your functions' results; * ints are interchangeably interpreted with either zero or nonzero * for success, but values of this type have fixed meaning. * * You may extend the meaning of this type in your code by instead * returning integer values other than SUCCESS_FAIL or SUCCESS_PASS, * but ensure that all failure values are less than or equal to * SUCCESS_FAIL, all success values are greater than or equal to * SUCCESS_PASS, and all warning values are in between. * * Because the values given below are subject to change, special * values should be expressed as deltas, e.g. SUCCESS_FAIL - 5. If * you need more than 64 warning values, etc., consider instead using * an additional pointer argument to return an error code. */ typedef enum { /** Upper-bound value indicating failed operation. */ SUCCESS_FAIL = 63, /** A generic warning value. */ SUCCESS_WARN = 96, /** Lower-bound value indicating successful operation. */ SUCCESS_PASS = 128 } success_t; /** * True on SUCCESS_PASS or greater; false otherwise. * * Distinct from !FAILED(x). Optimized for the passing case. */ #define PASSED(x) (likely((x) >= SUCCESS_PASS)) /** * True on SUCCESS_FAIL or less; false otherwise. * * Distinct from !PASSED(x). Optimized for the non-failing case. */ #define FAILED(x) (unlikely((x) <= SUCCESS_FAIL)) /** * Asserts that an operation succeeds; otherwise, aborts. * * This optimized check occurs regardless of debug mode. */ #define MUST_PASS(x) \ (likely(x >= SUCCESS_PASS) ? NOP : FATAL("MUST_PASS failed: %s", #x)) /** * Asserts that an operation does not fail; otherwise, aborts. * * This optimized check occurs regardless of debug mode. */ #define MUST_NOT_FAIL(x) \ (likely(x > SUCCESS_FAIL) ? NOP : FATAL("MUST_NOT_FAIL failed: %s", #x)) /** Converts C library non-negative success into a success_t. */ #define SUCCESS_FROM_C(x) (unlikely((x) < 0) ? SUCCESS_FAIL : SUCCESS_PASS) EXTERN_C_END #endif /* BASE_COMMON_H */