Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...


Balance Braces and Parentheses

  • Use parentheses anywhere it makes it easier for the reader
  • Make sure braces, parentheses, etc. match, even in the presence of preprocessor directives: put opening curly brace after #endif so that your editor won't see more opening braces than closing.
  • Right (braces are balanced):


    #ifdef WIN32
            for (i = 0; i <= max_connection && n; i++)/*  for select() in WIN32 */
    #else
            for (i = 0; i <= maxfdx && n; i++)/* for poll() in Unix */
    #endif
                     {
                    if (selpoll_fd_isset(i)) { /* this socket has data */
                                               n--; /* decrement the no. of events */
                                               ...
                    }
            }


    Wrong (braces are unbalanced -- note one in each for loop):


    #ifdef WIN32
            for (i = 0; i <= max_connection && n; i++) { /*  for select() in WIN32 */
    #else
            for (i = 0; i <= maxfdx && n; i++) { /* for poll() in Unix */
    #endif
                    if (selpoll_fd_isset(i)) { /* this socket has data */
                                               n--; /* decrement the no. of events */
                                               ...
                    }
            }


  • Balance your parentheses inside your #ifdefs.  Don't close parentheses inside an #ifdef if it was opened outside of the #ifdef.
  • Right:


    static void reap_child(void)
    {
    struct work_task *ptask;
            for (ptask = (struct work_task *)GET_NEXT(task_list_event);ptask;
                 ptask = (struct work_task *)GET_NEXT(ptask->wt_linkall)) {
                    if ((ptask->wt_type == WORK_Deferred_Child) &&
    #ifdef WIN32
                       ((HANDLE)ptask->wt_event == pid)
    #else
                       (ptask->wt_event == pid)
    #endif
                                            )
                            {
                            ...
                            }
                    }
            }
    }


    Wrong:


    static void reap_child(void)
    {
    struct work_task *ptask;
            for (ptask = (struct work_task *)GET_NEXT(task_list_event);ptask;
                 ptask = (struct work_task *)GET_NEXT(ptask->wt_linkall)) {
                    if ((ptask->wt_type == WORK_Deferred_Child) &&
    #ifdef WIN32
                        ((HANDLE)ptask->wt_event == pid))
    #else
                        (ptask->wt_event == pid))
    #endif
                            {
                            ...
                            }
                    }
            }
    }


C++ Standards

Follow the C Coding Standards, then look here for C++ specific guidelines.

File Extensions

Source files should use .cpp
Header files should use .hpp

Because we a mixed C/C++ project, it is helpful to know which header files we can use in a C file. Therefore, a C header should have a different extension than a C++ header.

.hpp is chosen because it easily attributed to .cpp files.

From the Boost FAQ:

File extensions communicate the "type" of the file, both to humans and to computer programs. The '.h' extension is used for C header files, and therefore communicates the wrong thing about C++ header files... Using '.hpp' unambiguously identifies it as C++ header file, and works well in actual practice. (Rainer Deyke)

Whitespace

We use tabs to be consistent with our C code.

Because we use tabs, we can’t use partial indents.
We don’t want to have a ton of horizontal white space making our lines longer than it has to be.

Classes will not have an indent before public, protected and private

// Bad
class MyClass {
  public:
    MyClass();
    ~MyClass();
  private:
    int count;
};

// Good
class MyClass {
public:
  MyClass();
  ~MyClass();
private:
  int count;
};

Namespaces will not cause a level of indentation

namespace pbs {
// Bad
  int add(int x, int y);
// Good
int add(int x, int y);
}

Names and Orders of Includes

  1. pbs_config.h if needed

  2. System and STL headers

  3. pbs headers

Some good things to keep in mind

Casting

Do not use C-style casts; instead use C++ style casts.

// Bad
int *p = (int *)malloc(sizeof(int));
// Good
int *p = static_cast<int *>(malloc(sizeof(int)));

Note: Void pointers can't be assigned to non-void pointers without a cast.

Use const char * whenever possible

If you're not changing a char * argument, use const in the function definition

// Bad
void
logmsg(int sev, char *msg)
{
  printf("%d\t%s\n", sev, msg);
  return;
}
// Good
void
logmsg(int sev, const char *msg)
{
  printf("%d\t%s\n", sev, msg);
  return;
}

Prefer nullptr to NULL

NULL is often just defined 0, nullptr is a pointer type pointing to the address 0x0.

// Bad
int *p = NULL;
// Good
int *p = nullptr;

auto is awesome

A lot of types can be very long strings, such as classes with templates. auto lets you save some typing by deducing the type from the right-hand-side.

// bad
std::vector<MyClass> list = std::vector<MyClass>();
// good
auto list2 = std::vector<MyClass>();

Namespaces

Using using namespace <name> is not a good idea, as it can pollute the global namespace. Instead, use the namespace prefix.

// Bad
using namespace std;
auto vec = vector<int>();
// Good
auto vec = std::vector<int>();

If you’re in the pbs namespace, don’t create another namespace prefixed with pbs_

// Bad
namespace pbs {
namespace pbs_util {
int count_spaces(const char *);
}
}
int spaces = pbs::pbs_util::count_spaces("    ");

// Good
namespace pbs{
namespace util {
int count_spaces(const char *);
}
}
int spaces = pbs::util::count_spaces("    ");

Unique Pointers

You can find an example of unique pointers here: https://openpbs.atlassian.net/wiki/spaces/PD/pages/2172551169/Unique+Pointer+Example

Inheritance/Polymorphism

You can find an example of these OOP features here: https://openpbs.atlassian.net/wiki/spaces/PD/pages/2191458305

Shell Scripts

  • PBS assumes that its shell scripts can use the executable script (#!) construct, and that #!/bin/sh suffices.


...