Vstuff coding rules
From VoiSmart Open Source Wiki
vStuff conforms to the Linux kernel's coding style and rules. Additionally I'm conforming to several rules:
Contents |
Object Orientation
Who says you can't do object oriented programming in C? Of course you can. Of course there you have the freedom to screw everything up, but it's not a stricter language that makes a better programmer :)
Objects are implemented by means of structures and functions acting on those structures which are the methods.
Naming is important. If the object is named foo, its methods should use foo_ as prefix and have "struct foo *foo" as their first parameter.
Reference Counting
Pointers to objects in a big projects tend to spread in an incontrollable way, thus, memory deallocation for those object may become tricky since coordinating who is responsible for the deallocation often involves the coordination of everyone handling a pointer to the object.
A good approach to this problem is the use of reference counting. Linux kernel makes extensive use of reference counting to handle memory management of its objects. vStuff follows this approach too.
Every object has its kref structure containing a reference counter. The reference counter counts how many users are holding a reference (a pointer) to the object. As long as the reference counter is greater than zero the memory must not be freed.
A little cooperation is required from the users. When creating a reference (copying a pointer to the object) the reference counter must be increased, when the pointer is discarded the reference counter must be decremented.
This is accomplished by using two methods named objectname_get() and objectname_put().
struct object *obj, *obj2;
obj = objectname_create(...);
obj2 = objectname_get(obj); [...work on obj2...] objectname_put(obj2); obj2 = NULL;
Garbage Collector
The garbage collector is the entity in charge of actually freeing the memory associated with an object. In its simple form it just waits for the reference counter to reach zero and then frees the associated resources. In Linux's kernel the garbage collector is in kref_put().
The most annoying drawback of reference counting takes place when an object may refer to other objects which in turn may refer to the original object. If nobody external to the reference chain is holding a reference to an object, the chain's objects may effectively be released, however, having a reference count greater than zero, the objects will not be released by a simple garbage collector like the kernel's.
This circular reference requires a smart garbage collector, able to detect and break circular references when appropriate; unfortunately this kind of garbage collector is way more complex than the simple refcnt==0 check and its implementation in the Linux kernel is probably out of question.
Reserved Methods
Some method names are reserved for specific "standard" behavior. Here follows a list of the standard methods:
struct foo *foo_create(struct foo *foo, /* Initial state */);
The _create suffix is reserved for the constructor. The constructor may allocate the object itself if foo==NULL or work on a preallocated space if foo is non-NULL. The latter is useful if the object is contained in a preallocated, maybe static, area. The constructor returns a pointer to the object created or NULL if the allocation failed. The pointer is the first valid reference to the object and it can be put by using foo_put().
struct foo *foo_get(struct foo *foo); void foo_put(struct foo *foo);
As seen before, foo_get() and foo_put() manage reference counting.
void foo_destroy(struct foo *foo);
The destroy method is used to release references to other objects and wait for the reference counter to become 1, then put() the last reference.

