# The UCX code style ## Style * 4 spaces, no tabs * up to 80 columns * single space around operators * no spaces in the end-of-line * indent function arguments on column * indent structure fields on column * scope: open on same line, except function body, which is on a new line. * indent multiple consecutive assignments on the column * 2 space lines between types and prototypes (header files) * 1 space line between functions (source files) ## Naming convention: * lower case, underscores * names must begin with ucp_/uct_/ucs_/ucm_ * macro names must begin with UCP_/UCT_/UCS_/UCM_ * an output argument which is a pointer to a user variable has _p suffix * value types (e.g struct types, integer types) have _t suffix * pointer to structs, which are used as API handles, have _h suffix * macro arguments begin with _ (e.g _value) to avoid confusion with variables * no leading underscores in function names * ### Header file name suffixes: * _fwd.h for a files with a types/function forward declarations * _types.h if contains a type declarations * .inl for inline functions * _def.h with a preprocessor macros ## C++ * used only for unit testing * lower-case class names (same as stl/boost) ## Include order: 1. config.h 2. specific internal header 3. UCX headers 4. system headers ## Doxygen * all interface H/C files should have doxygen documentation. ## Error handling * all internal error codes must be ucs_status_t * a function which returns error should print a log message * the function which prints the log message is the first one which decides which error it is. If a functions returns an error because it's callee returned erroneous ucs_status_t, it does not have to print a log message. * destructors are not able to propagate error code to the caller because they return void. also, users are not ready to handle errors during cleanup flow. therefore a destructor should handle an error by printing a warning or an error message. ## Testing * every major feature or bugfix must be accompanied with a unit test. In case of a fix, the test should fail without the fix. ## Examples ### if style Good ```C if (val != XXX) { /* snip */ } else if (val == YYY) { /* code here */ } else { /* code here */ } ``` Bad ```C if(val != XXX) { /* Require space after if */ if (val != XXX){ /* Require space after ) */ if ( val != XXX) { /* Remove space after ( */ ``` ### goto style Good ```C err_free: ucs_free(thread); err: --ucs_async_thread_global_context.use_count; out_unlock: ucs_assert_always(ucs_async_thread_global_context.thread != NULL); *thread_p = ucs_async_thread_global_context.thread; ``` Bad ```C err_free: ucs_free(thread); /* !!!Remove this line!!! */ err: --ucs_async_thread_global_context.use_count; ``` ### structure assignment Good ```C event.events = events; event.data.fd = event_fd; event.data.ptr = udata; ``` Bad ```C /* Align = position */ event.events = events; event.data.fd = event_fd; event.data.ptr = udata; ``` ### comment in C file Good ```C /* run-time CPU detection */ ``` Bad: require C style `/* .. */` comment. ```C // run-time CPU detection ``` ### no spaces in the end-of-line Good ```C int fd; ``` Bad ``` int fd; /* ^^ Remove trailing space */ ``` ### macro definition Good ```C #define UCS_MACRO_SHORT(_obj, _field, _val) \ (_obj)->_field = (_val) #define UCS_MACRO_LONG(_obj, _field1, _field2, _val1, _val2) \ { \ ucs_typeof((_obj)->_field1) sum = (_val1) + (_val2); \ \ (_obj)->_field1 = sum; \ (_obj)->_field2 = sum; \ } #define UCS_MACRO_LONG_RET_VAL(_obj, _field, _val, _func) \ ({ \ ucs_status_t status; \ \ (_obj)->_field = (_val); \ \ status = _func(_obj); \ status; \ }) ``` Bad ```C #define UCS_MACRO_SHORT(_obj, _field, _val) \ _obj->_field = _val /* need to wrap macro arguments by () */ #define UCS_MACRO_LONG(_obj, _field1, _field2, _val1, _val2) \ /* possible mixing declarations and code */ \ typeof((_obj)->_field1) sum = (_val1) + (_val2); \ \ (_obj)->_field1 = sum; \ (_obj)->_field2 = sum; #define UCS_MACRO_LONG_RET_VAL(_obj, _field, _val, _func) \ ({ \ ucs_status_t status; \ \ (_obj)->_field = (_val); \ \ status = _func(_obj); \ status; \ }) /* wrong alignment of "\" */ ```