Main  /  Edit this version (rollback)  /  Edit  /  History  /   /  Users Area

Coding Standards for CppCMS 1.x.x

(version 7, from 2009-09-04 16:40:19)

Coding Style

Keeping backward compatible ABI

One of the major goals of CppCMS is keeping stable backward compatible API and ABI the way it is done in Qt framework. This is not simple task to do in C++. So in order to achieve this goal following should be done:

  1. All user API should use only standard natively supported C++ classes and libraries – STL.
  2. No 3rd part libraries API should be ever exposed to user – including but not limited to – Boost.
  3. All classes with exception of extremely simple ones with very limited and well defined functionality should include opaque pointer in order to ensure that adding or removing class member would break ABI.

This is a very good reference written for KDE on how not to break ABI. READ IT!!!

How to write classes

For example:

Header:

// foo.h
class foo : public util::noncopyable {
public:
   foo(); // Always should be non-inlined constructor
   ~foo(); // Always should be non-inlined destructor
   int x() const; // getter
   void x(int );  // setter
private:
   struct data;
   util::hold_ptr<data> d;   
};

Implementation:

// foo.cpp
struct foo::data {
    int x;
};

foo::foo() : d(new foo::data()) 
{
}
foo::~foo()
{
}
int foo::x() const { return d->x; }
void foo::x(int v) { d->x=v; }

F.A.Q.

  1. But how can I use (Put Boost Library Name) in the code?

    Use it, just never expose it in user API.

  2. But how can I write callbacks without boost::function?

    Use internal simple implementation of callbackX.h it provides most of functionality.

  3. What about boost::signal?

    Wrap a linked list of callbacks with your favorite API.

  4. What about boost::bind?

    Are you sure you need to use bind in headers?

    If so, there are simple member function binders implemented in mem_bind.h. If it not suit your needs just create simple copyable class with operator().

  5. What about boost::shared_ptr?

    Unfortunately boost implementation of shared_ptr has some issues for keeping ABI – the reference counter implementation depended on some macros, so simple define may break ABI if shared_ptr is disclosed to user. Also, C++0x shared_ptr is still not widely supported. So you can’t use shared_ptr in CppCMS API.

  6. Where do I get reference counting smart pointers for CppCMS?

    CppCMS had grabbed local copy of boost::intrusive_ptr and implemented thread-safe atomic counter that is kept ABI safe.

    So any class that should be used with reference counting can be simply derived from refcounted class that provides expected functionality.

    intrusive_ptr is not as powerful as shared_ptr because it lacks weak references, but it is good enough for most of cases, also, its flexibility allows keeping finer semantics – for example, you may not destroy the object but recycle it to pool like it is done for cppcms::application.

General Coding Notes

Exceptions

All code you write should be exception safe. Only functions that you may assume they never throw exceptions are POSIX API or 3rd party C libraries like libgcrypy or sqlite3. Even STL may throw exception. Assume that std::bad_alloc may be thrown and handle it correctly.

Thus:

STL

Do not reinvent the wheel, use STL — it is well document, well known, highly available library that does the job. Use it.

Notes:

  1. Always prefer std::vector to std::list — it has better performance because it is cache friendly.
  2. Always prefer std:string for text storage.
  3. It is OK to return STL collections from functions, compiler know how to optimize them.
  4. Do not forget swap() function — it can save lot’s of unnecessary copies for you. For example:

    vector<char> foo();
    ...
    void bar() 
    {
       vector<char> s;
       for(;;) {
         s.swap(foo());
         // Not s=foo();
         if(s.empty())
           break;
       }
    }
    
    Description: when you call s=foo() assignment operator is called that copies the value that foo() returned to s and then releases it. When you call s.swap(foo()) the value in s is replaced by returned value and the old value in s is cleaned — you saved copy of probably huge buffer, you operation is done in O(1).
  5. If you have non-copyable class, you can store it in STL collection using reference counting pointer.

Libraries

Boost

CppCMS should work with at least Boost 1.36.

Generally prefer boost over other libraries, however use Boost features carefully, or do not use at all. Examples:

  1. Boost Interprocess too "heavy" and little bit "ugly" because it supports windows and supports placing any objects in memory. The nature of fork() gives much better functionality and allows placing any object in shared memory every time it use shared memory allocators.

    So use it only as replacement of libmm.

  2. Boost Serialization – has too many performance overheads – don’t use it.

Licenses

  1. All libraries should be OpenSource libraries
  2. Prefer non-copyleft licenses like MIT, 3 clause BSD, Boost over copyleft one, like LGPL.
  3. All libraries, CppCMS uses should be compatible with LGPLv2.
  4. You may use strong copyleft libraries for stand alone utilities that are not linked with CppCMS framework.

    For example: If you want to write GUI for cppcms_tcp_scale utility using Qt you are welcome.

Using

If you want to add an additional dependency for CppCMS make sure:

  1. Check if boost has implementation of such feature.
  2. There is a big value for adding such dependency.
  3. This library is highly available.
  4. You checked all alternatives and decided that this one is the best.
  5. You had added an autoconf macro and conditional build for CppCMS that allows building all framework without this library.

For example, libgcrypt:

About

Wiki++ is a wiki engine powered by CppCMS web development framework.

Mirrors

Hosted By

SourceForge.net Logo


Navigation

Main Page


Valid CSS | Valid XHTML 1.0