Previous section   Next section

Imperfect C++ Practical Solutions for Real-Life Programming
By Matthew Wilson
Table of Contents
Chapter 3.  Resource Encapsulation


3.2. POD Types

POD type encapsulation is the most basic form where some effort has been to increase robustness, by virtue of aggregating one or more resource references in a structure.

Let's imagine we have some notional network server that provides a selection of services based on different client requirements. Each service is represented by the following structure:



struct Service


{


  socket_t  txChannel;    // transmission socket


  socket_t  rxChannel;    // reception socket


  mutex_t   *lock;        // service mutual exclusion object


  byte_t    *txBuffer;    // transmission buffer


  size_t    txBufferSize; // # of bytes in transmission buffer


  byte_t    *rxBuffer;    // reception buffer


  size_t    rxBufferSize; // # of bytes in reception buffer


};



3.2.1 Direct Manipulation

The most primitive manner of manipulating a Service would look something like the following:



Service  service;





. . . // Initialize the service, and make some connections





pthread_mutex_lock(service.lock);


int i = recv( service.rxChannel, service.rxBuffer


            , service.rxBufferSize);


. . . // Many more lines of low-level coding


pthread_mutex_lock(&service.unlock);



This kind of coding is really hard to do, and doubly so to ensure quality and maintainability. If the definition of Service is changed, there can be thousands of lines of code that need to change. There are some well-known APIs that make you do a lot of this manually, but thankfully most C APIs come along with many functions that help you out.

3.2.2 API Functions and Transparent Types

Naturally, if you were using the Service API you'd hopefully be using (or writing, if they didn't already exist) API functions to manipulate the Service structure at a higher level, such as:



int i = Service_GuardedReceive(&service, . . .);



This is one of the most common programming models around. It is very usable and reasonably safe. Many an operating system has been built in this fashion. Nonetheless, there are still problems; it is insufficiently encapsulated. Since the client code has access to the structure, the temptation for users of the API to fiddle just here and there can be too great. Even if they only peek at the structures, and don't change anything, a reliance on the format of the structure still represents a brittle code set, and can make maintenance a big challenge.

3.2.3 API Functions and Opaque Types

If the client code has no need of access to the structure, or the risk of direct access is too great, the API function model is enhanced markedly by making the structures opaque. There are several ways to do this; it usually takes the form of declaring a structure, but not defining it publicly.



// ServiceAPI.h





struct Service;





int Service_Create(. . . init parameters . . . , Service **svc);


int Service_Open(. . . init parameters . . . , Service **svc);


int Service_Destroy(Service *svc);


int Service_GuardedReceive(Service *svc, . . . );



Only in the API implementation is the Service structure defined, and so client code neither knows nor cares about its actual structure. And, more important, it cannot peek at the structure contents and introduce breakable dependencies.

There's a slight refinement of this, allowing for a greater syntactic opacity, which is helpful, albeit that it has no deeper significance.



// ServiceAPI.h





struct ServiceInternal;


typedef struct ServiceInternal *Service;





int Service_Create(. . . init parameters . . . , Service *svc);


int Service_Open(. . . init parameters . . . , Service *svc);


int Service_Destroy(Service svc);


int Service_GuardedReceive(Service svc, . . . );



Now Service is not a structure, to which one must manipulate pointers, but rather an opaque type. For those who like a bit of syntactic sugar, this might be called HService, to denote that it is a handle to a service.


      Previous section   Next section