Skip to content
This repository has been archived by the owner on Aug 11, 2020. It is now read-only.

Coding style

Rick Zhou edited this page Jan 24, 2018 · 12 revisions

targeting GCC 4.9, use only C++11 feature, not 14 or 17 features

  • auto keyword is an exception, it's well supported in gcc 4.9

use google style to format the code , already defined in .clang-format file

use smart pointer, avoid doing things in destructor

  • doing this allows us to port the code to other GC based language easily
  • define destructor only when having compiling issue with undefined type (forward-declared only). in this case, define destructor in cc file and use empty function body

carefully design data structure with ref_ type so they can never be accessed in multi-thread

  • the ref_ type is based on boost:intrusive_ptr
  • ref_ type is a smart pointer that's designed for performance but not thread safety
  • anything touching one ref_ must run in same strand, unless:
    • when object is created in one strand/thread and send to other strand at once, the original strand completely forget about the instance
    • in unit test, when knowing at a certain time all code are idle and nothing will read/write the ref_

don't use boost feature if it's already in std

for example, std::mutex

don't use boost::bind or std::bind, always use lambda

NEVER DO THIS:

  • pointer is lost after that function returned and cannot be deleted anymore
StorageBucket& SimpleStorage::get_bucket(const std::string& name) {
  return *(new SimpleStorageBucket(_io_service));
}

instead do this

std::unique_ptr<StorageBucket> SimpleStorage::get_bucket(const std::string& name) {
  return std::unique_ptr<StorageBucket>(new SimpleStorageBucket(_io_service));

ALWAYS DO THIS

  • Write virtual deconstructor as default if at least one virtual function defined in that class. Otherwise it causes "new delete mismatch" issue
virtual ~StorageBucket() = default;

BE CAREFUL

Cyclic reference: (if possible, avoid)

  • If a class has some properties that shares the same ref_ of the parent class, always create that class with "make_ref_". For example, Session has two properties called _ack_stream and _ping_stream which shares the parent Session object.
auto s3 = make_ref_<Session>(config, "hello");

don't do this:

Session s(config, "hello");

or

Session* s2 = new Session(config, "hello");
  • Do not trust the ref_ to free your object. It is not working if your object has cyclic reference. For these type of objects, if you don't want to cause memleak, you should inherit DestroyableRef and implement destroy_impl to reset all the parent objects ref_. And you should not forget to call destroy function after you have done with this object. Don't let these objects go away.