cru_function_types - function types defined and used by the cru library
#include <cru/cru.h>
Many cru library API functions have arguments that are pointers to C structs meant to be initialized in advance by the caller, with some of their fields initialized as pointers to user-defined "callback" functions. Each callback function is required to conform to one of the prototypes documented in this manual and to adhere to certain other calling conventions.
As an overview, callback functions can be classified as
where x can be one of n , u , b , t or q for nullary, unary, binary, ternary or quarternary. All parameters to operators and predicates are untyped pointers or compatibly sized scalars cast as such, except for the last parameter, which is a pointer to a signed integer. The choice between scalars and pointers depends on how an application developer chooses to represent graphs and their properties.
When operators with type definitions of the form cru_xop return a pointer to dynamic storage, convenience and probably performance are favored by having it allocate a new one on each invocation. However, applications may opt to trade performance for space efficiency by returning a pointer to a shared copy when sharing is possible. In this case, both the operator and the corresponding cru_destructor are responsible for managing a thread-safe reference counting scheme whose validity is not enforceable by cru using pthreads primitives or alternatives.
The integer pointer required as the last parameter to most callback functions, denotable as err, is usable by applications to report error conditions. For example, if a callback function needs to allocate memory for whatever reason but fails because malloc returns NULL, it can instead assign a value of ENOMEM to *err as defined in the system header file <errno.h>. Any non-zero value assigned to *err causes an orderly termination of the API function that called the callback function and makes it report the same error condition to its caller. The application is not otherwise interrupted and can continue. Some further considerations are relevant:
Some additional calling conventions concern mutability and concurrency.
A callback function passed a pointer to the heap should never free or deallocate it unless that function is specifically designated as a cru_destructor. In other words, callback functions other than destructors are expected only to "borrow" their arguments, not to "consume" them.
Similarly, callback functions passed vertices, edge labels, or vertex properties should treat them as read-only and not attempt to modify them in place for any reason other than reference counting as noted above, whose thread safety becomes the responsibility of the application. If the operand is a scalar value, modifying it has no persistent effect. If it is a pointer, modifying the memory it references (for example, by marking it "visited") may cause a data race or may non-deterministically expose inconsistent views of the graph to other worker threads. Graph mutation and traversal should be effected only according to the supported API.
If a callback function interacts with storage or other resources unrelated to cru (such as profilers or databases), it must do so in a thread-safe way, for example by using pthreads mutex locking mechanisms, under the assumption that the same code may be running in many threads. Thread-safe access without locking is provided only to graphs cru creates and only through the supported API.
This user-defined function tests whether two vertices coincide by pointer equality. The error parameter is required by the API even if not by the function.
int my_equality (cru_vertex x, cru_vertex y, int *err) { return (x == y); }
Cast to a cru_bpred, this function can be used in a declaration such as the following.
struct cru_order_s my_vertex_order = { .equal = (cru_bpred) my_equality};
/usr/local/include/cru/cru.h
/usr/local/include/cru/data_types.h
/usr/local/include/cru/function_types.h
/usr/local/include/cru/error_codes.h
cru, cru_bop, cru_bpred, cru_builder, cru_built, cru_cbop, cru_classifier, cru_class_of, cru_class_size, cru_composed, cru_composer, cru_connect, cru_connector, cru_cqop, cru_crossed, cru_crosser, cru_ctop, cru_ctop_pair, cru_ctop_quad, cru_data_types, cru_deduplicated, cru_destructor, cru_destructor_pair, cru_edge_count, cru_fabricated, cru_fabricator, cru_filter, cru_filtered, cru_fold, cru_free_kill_switch, cru_free_later, cru_free_now, cru_free_partition, cru_get, cru_hash, cru_induced, cru_inducer, cru_kernel, cru_kill, cru_killed, cru_mapreduced, cru_mapreducer, cru_merged, cru_merger, cru_mutated, cru_mutator, cru_new_kill_switch, cru_nop, cru_order, cru_order_pair, cru_partition_of, cru_plan, cru_postponed, cru_postponer, cru_prop, cru_prop_pair, cru_pruner, cru_qop, cru_qpred, cru_set, cru_sig, cru_singleton, cru_split, cru_splitter, cru_spread, cru_strerror, cru_stretch, cru_stretched, cru_stretcher, cru_subconnector, cru_terminus_count, cru_top, cru_tpred, cru_united, cru_uop, cru_vertex_count, cru_zone
Dennis Furey (milonga@delayinsensitive.com)
https://github.com/gueststar/cru