1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
//------------------------------------------------------------------------------
// GB_context.h: definitions for the internal context
//------------------------------------------------------------------------------
// SuiteSparse:GraphBLAS, Timothy A. Davis, (c) 2017-2022, All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
//------------------------------------------------------------------------------
#ifndef GB_CONTEXT_H
#define GB_CONTEXT_H
//------------------------------------------------------------------------------
// GB_context: error logging, thread control, and Werk space
//------------------------------------------------------------------------------
// Error messages are logged in Context->logger_handle, on the stack which is
// handle to the input/output matrix/vector (typically C). If the user-defined
// data types, operators, etc have really long names, the error messages are
// safely truncated (via snprintf). This is intentional, but gcc with
// -Wformat-truncation will print a warning (see pragmas above). Ignore the
// warning.
// Threading control is described in GB_nthreads.h.
// GB_WERK_SIZE is the size of a small fixed-sized array in the Context, used
// for small werkspace allocations (typically O(# of threads or # tasks)).
// GB_WERK_SIZE must be a multiple of 8. The Werk array is placed first in the
// GB_Context struct, to ensure proper alignment.
#define GB_WERK_SIZE 16384
typedef struct
{
GB_void Werk [GB_WERK_SIZE] ; // werkspace stack
double chunk ; // chunk size for small problems
const char *where ; // GraphBLAS function where error occurred
char **logger_handle ; // error report
size_t *logger_size_handle ;
int nthreads_max ; // max # of threads to use
int pwerk ; // top of Werk stack, initially zero
}
GB_Context_struct ;
typedef GB_Context_struct *GB_Context ;
// GB_WHERE keeps track of the currently running user-callable function.
// User-callable functions in this implementation are written so that they do
// not call other unrelated user-callable functions (except for GrB_*free).
// Related user-callable functions can call each other since they all report
// the same type-generic name. Internal functions can be called by many
// different user-callable functions, directly or indirectly. It would not be
// helpful to report the name of an internal function that flagged an error
// condition. Thus, each time a user-callable function is entered, it logs the
// name of the function with the GB_WHERE macro.
#define GB_CONTEXT(where_string) \
/* construct the Context */ \
GB_Context_struct Context_struct ; \
GB_Context Context = &Context_struct ; \
/* set Context->where so GrB_error can report it if needed */ \
Context->where = where_string ; \
/* get the default max # of threads and default chunk size */ \
Context->nthreads_max = GB_Global_nthreads_max_get ( ) ; \
Context->chunk = GB_Global_chunk_get ( ) ; \
/* get the pointer to where any error will be logged */ \
Context->logger_handle = NULL ; \
Context->logger_size_handle = NULL ; \
/* initialize the Werk stack */ \
Context->pwerk = 0 ;
// C is a matrix, vector, scalar, or descriptor
#define GB_WHERE(C,where_string) \
if (!GB_Global_GrB_init_called_get ( )) \
{ \
return (GrB_PANIC) ; /* GrB_init not called */ \
} \
GB_CONTEXT (where_string) \
if (C != NULL) \
{ \
/* free any prior error logged in the object */ \
GB_FREE (&(C->logger), C->logger_size) ; \
Context->logger_handle = &(C->logger) ; \
Context->logger_size_handle = &(C->logger_size) ; \
}
// create the Context, with no error logging
#define GB_WHERE1(where_string) \
if (!GB_Global_GrB_init_called_get ( )) \
{ \
return (GrB_PANIC) ; /* GrB_init not called */ \
} \
GB_CONTEXT (where_string)
//------------------------------------------------------------------------------
// error logging
//------------------------------------------------------------------------------
// The GB_ERROR macro logs an error in the logger error string.
//
// if (i >= nrows)
// {
// GB_ERROR (GrB_INDEX_OUT_OF_BOUNDS,
// "Row index %d out of bounds; must be < %d", i, nrows) ;
// }
//
// The user can then do:
//
// const char *error ;
// GrB_error (&error, A) ;
// printf ("%s", error) ;
GB_PUBLIC
const char *GB_status_code (GrB_Info info) ;
// maximum size of the error logger string
#define GB_LOGGER_LEN 384
// log an error in the error logger string and return the error
#define GB_ERROR(info,format,...) \
{ \
if (Context != NULL) \
{ \
char **logger_handle = Context->logger_handle ; \
if (logger_handle != NULL) \
{ \
size_t *logger_size_handle = Context->logger_size_handle ; \
(*logger_handle) = GB_CALLOC (GB_LOGGER_LEN+1, char, \
logger_size_handle) ; \
if ((*logger_handle) != NULL) \
{ \
snprintf ((*logger_handle), GB_LOGGER_LEN, \
"GraphBLAS error: %s\nfunction: %s\n" format, \
GB_status_code (info), Context->where, __VA_ARGS__) ; \
} \
} \
} \
return (info) ; \
}
#endif
|