Skip to content

Latest commit

 

History

History
292 lines (232 loc) · 6.89 KB

CodeStyle.md

File metadata and controls

292 lines (232 loc) · 6.89 KB

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)
  • The unit tests in test/gtest are written using C++11. Whenever applicable, the usage of advanced language features is allowed and preferred over legacy code. For example:

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.
  • Using status for ucs_status_t and ret for int is preferred.
  • 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.

Miscellaneous examples

Boolean expression

Use explicit checks with added parenthesis like below.

Good

    if (ptr == NULL) {

    if (a == 0) {

    if ((ret == UCS_KH_PUT_BUCKET_EMPTY) ||
        (ret == UCS_KH_PUT_BUCKET_CLEAR)) {

Variable definition

Variables defined with a value should be first. Add a blank line after definitions.

void function(int value)
{
    int a     = 1;
    void *ptr = &value;
    int b;
    ucs_status_t status;

    a += value;

if style

Use blank line after if/else blocks

    if (value > 0) {
        value = 23;
    } else {
        value = 12;
    }

    value *= 2;

Check return values close to functions

Good

    if (val != XXX) {
        ret = f1();
        if (ret < 0) {
        }
        ...
    } else {
        ret = f2();
        if (ret < 0) {
        }
        ...
    }

Bad

    if (val != XXX) {
        ret = f1();
        ...
    } else {
        ret = f2();
        ...
    }

    if (ret < 0) {

    }

General formatting rules

Good

    if (val != XXX) {
        /* snip */
    } else if (val == YYY) {
        /* code here */
    } else {
        /* code here */
    }

Bad

    if(val != XXX) {   /* Require space after if */
    if (val != XXX){   /* Require space after )  */
    if ( val != XXX) { /* Remove space after (   */

goto style

Labels should be named preferably out, err or with prefix err_/out_.

Good

    return;

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

    return;
/*    !!!Add blank line!!!      */
err_free:
    ucs_free(thread);
/*    !!!Remove this line!!!    */
err:
    --ucs_async_thread_global_context.use_count;

structure assignment

Good

    event.events   = events;
    event.data.fd  = event_fd;
    event.data.ptr = udata;

Bad

    /* Align = position */
    event.events = events;
    event.data.fd = event_fd;
    event.data.ptr = udata;

comment in C file

Good

/* run-time CPU detection */

Bad: require C style /* .. */ comment.

// run-time CPU detection

no spaces in the end-of-line

Good

    int fd;

Bad

    int fd;  
        /* ^^ Remove trailing space */

macro definition

Good

    #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

    #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 "\" */