You are currently browsing the archives for the interface tag.

The hokey-cokey* of function calls

January 20th, 2014

Functions are the lifeblood of a C program. The program flow is altered by passing parameters to functions, which are then manipulated. Conceptually function parameters are defined as being either:

  • Inputs (Read-only) – client-supplied objects manipulated within the function only
  • Outputs (Write-only) – objects generated by the function for use by the client.
  • Input-Outputs (Read-Write) – client objects that can be manipulated by the function.

Defining the use of a parameter gives vital information not only to the implementer, but (perhaps more importantly) to the user of the function, by more-explicitly specifying the ‘contract’ of the function.

Many programming languages (for example, Ada) support these concepts explicitly. C, however, does not. One has to remember that when Kernighan and Ritchie developed C structured programming was very much in its infancy and many of these ideas were still being formulated (also remember that one of the C design goals was parsimony).

Even today, though, these concepts are rarely taught to C programmers and that has often led to clumsy, insecure or even downright dangerous APIs.

If C doesn’t support these concepts explicitly, can we simulate them? The answer is (of course) yes, by using some basic language constructs and forming some idioms.

Let’s look at each parameter type in turn.

Input parameters

C specifies a call-by-value or call-by-copy paradigm. That is, when a C function is called the compiler sets up a call frame that holds copies of the function parameters. Therefore, when you pass parameters by value you are – in effect – creating a parameter for the function to use that in no way affects the caller’s data

image

This is fine for simple types, but what about user-defined types – structs? What’s the problem with passing them by value?

image

Passing a structure by value means allocating enough memory for the parameter and then copying the contents of the original object into the parameter. In many embedded systems, where memory is at a premium, this could easily overflow the stack – at run-time, where its consequences could be difficult to track.

Strictly, to be explicit you should specify the type of the parameter as a const:

image

For simple types this is unlikely to add much value; however it may provide some benefit with structures.

If a parameter is passed as a const struct the compiler has the opportunity to perform a lazy evaluation – it passes the address of the structure instead of making a copy.

image

Note that this optimisation may not be supported by all compilers; or might not occur at all levels of optimisation.

Input-Output parameters

The resolution to the above problem is to explicitly pass a pointer to the structure:

image

This is clearly more efficient than copying the whole structure. OK, the syntax has got a little messier, but we can live with that.

But hang on: do we still have an Input parameter? Actually, no.

What we’ve got here is an input-output parameter. By passing a ‘raw’ pointer the function can manipulate the caller’s object. To fix this we need to prevent manipulation of the pointed-to object:

image

Still not quite there, though. What happens below?

image

Strictly we should make the pointer itself const to prevent (either accidently or maliciously) the function manipulating the caller’s object:

image

This is a very good general rule-of-thumb for functions: make all pointers const

Output parameters

An output parameter is one that the function can write to, but never read (i.e. write-only). In C the only real mechanism we have for that is the function return value.

Most programmers are happy to return simple types from functions but what about the following code?

image

Since C performs pass (and return!) by value this would appear very inefficient:

image

The original object (biiig) is constructed. Then, when makeBigStruct is called space for the return value is allocated. Inside makeBigStruct, temp is allocated. On return temp is copied into the return value then, finally, copied into biiig.

Knowing this, most programmers never return structures from functions; preferring instead to supply them as input-output parameters. However, most modern compilers provide an optimisation which does just this.

Below is the same code but showing the optimisation. Instead of returning the structure the address of the receiving object is (implicitly) passed to the function. At the end of the function the return value is copied into the receiver, negating the need for a temporary return object.

image

In general, then, it is OK to return a struct from a function by value (unless you’re using an ancient C compiler). If you’re not certain (or your compiler doesn’t support this optimisation) it’s probably safer for you to use input-output parameters instead.

Finally, it’s worth noting the small detail that, unlike other languages, a C function can only have one output parameter. You’ll need to use input-output parameters for the rest.

Making the world a better place.

Using these idioms consistently is a very good way to improve the quality of your code. Firstly, it allows the compiler to provide stronger checking on your code. Second, it gives the reader extra information about how to use your functions and what guarantee (or promise) they can expect from them.

You may have noticed I’ve ignored arrays in this article. Check out this blog post for passing arrays to functions.

In summary:

image

 

* Or, hokey-pokey if you prefer.

Interface adaption, and private inheritance

May 22nd, 2012

A problem with code re-use

It’s a common situation in software development: you’ve acquired a class – either from a third-party source, or inherited from another project – that’s got some really useful features, but its interface doesn’t quite meet your immediate needs. Two typical scenarios are:

  • The interface is too big; you just want your clients to have a small subset of the facilities on offer.
  • The interface signatures don’t match what your client code needs (and you don’t want to – or can’t – change the client code.

 

clip_image002

Figure 1 – A mis-match between the interface the client requires and the interface provided by the utility class

The solution is to use the Adapter pattern – encapsulate the useful class within an object of your own devising and present a new interface for your client. There are two approaches to creating adapters – wrapping an object (known as the Object Adapter pattern) and the (less-well-known) Class Adapter pattern, which uses private inheritance (for more details on these patterns see Design Patterns. Elements of Reusable Object-Oriented Software, p139).

The Object Adapter pattern

In the Object Adapter pattern the Adapter class implements the service interface as required by the client but contains a nested object that implements the actual behaviour (see Figure 2)

clip_image004

Figure 2 – The Object Adapter pattern

/////////////////////////////////////////////////////////////////////
//
class IService
{
public:
  virtual void service1() = 0;
  virtual void service2() = 0;
  virtual void service3() = 0;
  virtual void service4() = 0;
};

/////////////////////////////////////////////////////////////////////
//
class UtilityProvider
{
public:
  void func1();
  void func2();
  void func3();
  void func4();

protected:
  void helperFunction();
};

 

The ObjectAdapter class realises the IService interface, and encapsulates a UtilityProvider object. There are three ways the UtilityProvider object can be bound to the ObjectAdapter:

  • The UtilityProvider object can be created by the client then passed in to the constructor of the ObjectAdapter. This is how the pattern is implemented in Design Patterns; and how it is done in this example.
  • The UtilityProvider can be created as a composite, nested object.
  • The UtilityProvider object can be allocated from the free store in the ObjectAdapter’s constructor and de-allocated in the ObjectAdapter’s destructor.

All three options are viable; but be careful with the second two if the ObjectAdapter instance is going to be copied (you will need to ensure the UtilityProvider object is properly copied)

/////////////////////////////////////////////////////////////////////
//
class ObjectAdapter : public IService
{
public:
  ObjectAdapter(UtilityProvider& obj) : utilityObject(obj) {}

private:
  virtual void service1()   // Simple pass-through call... 
  {
    utilityObject.func1();
  }

  virtual void service2()   // Combining behaviours...
  {
    utilityObject.func1();
    utilityObject.func2();
  } 

  virtual void service3()
  {
    // ... 
  }

  virtual void service4()
  {
    utilityObject.helperFunction();  // ERROR - protected member 
  }

  UtilityProvider& utilityObject;
};

/////////////////////////////////////////////////////////////////////
//
int main()
{
  UtilityProvider provider;
  IService& client = *(new ObjectAdapter(provider));

  client.service1();
  client.utilityObject.func1();  // ERROR – private object.

  // ...

  delete &client;
}

 

Note our client depends only the interface; not on any particular implementation. We can substitute our ObjectAdapter class since it inherits from the IService class.

Our new methods can be used to change the names (or signatures) of the UtilityProvider class’s methods. We can even combine Useful methods behind a more abstract interface.

Note, however, we cannot get access to any protected members of UtilityProvider.

Our client code can access our methods, but cannot get access to any of the methods of the (privately) nested UtilityProvider object.

Using private inheritance – the Class Adapter

The Class Adapter pattern uses private inheritance to encapsulate the UtilityProvider’s behaviour and present a new interface.

clip_image006

Figure 3 – The ClassAdapter inherits from both the Interface and the Implementation

Normally when we do inheritance in C++ we use public inheritance. Public inheritance does not change the access modifiers from the base class to the derived class. So public members in the base remain public in the derived; protected members remain protected; and private members remain private.

With private inheritance, any public or protected members in the base class become private in the derived class; and therefore become unavailable to clients of the derived class.

We make use of the change of access modifiers in the Class Adapter pattern. The ClassAdapter publically inherits from the IService interface (so the client can call its methods) but privately from the UtilityProvider (thus hiding all those methods)

/////////////////////////////////////////////////////////////////////
//
class ClassAdapter : public  IService,       // Interface
                     private UtilityProvider // Implementation
{
private:
  virtual void service1()
  {
    UtilityProvider::func1();
  }

  virtual void service2()
  {
    UtilityProvider::func1();
    UtilityProvider::func2();
  }

  virtual void service3()
  {
    // ... 
  }
  virtual void service4()
  {
    UtilityProvider::helperFunction();  // OK – Can access protected
  }
};

/////////////////////////////////////////////////////////////////////
//
int main()
{
  IService& client = *(new ClassAdapter);

  client.service1();

  // ...

  delete &client;
}

 

As before, we can add new methods to the Adapter class public interface. These methods then call on the base class operations. Again, we can combine methods to present a more abstract interface.

In addition, now we can access the protected members of the Useful class.

Simplifying an interface – the Adapting Façade

Often your client isn’t dependent on an interface, but you still might want to modify the interface of your utility class. Typically you’ll want to change a few methods and/or provide a subset of the original class’s interface.

Strictly, this isn’t the Adapter pattern. It’s actually a variation of the Façade pattern (Design Patterns. Elements of Reusable Object-Oriented Software, p187). The Façade pattern is designed to simplify access multiple subsystems, or non-OO APIs with a single, unified interface. In this case we only have one subsystem, our utility class. Let’s call it an Adapting Façade (for want of a better term).

/////////////////////////////////////////////////////////////////////
//
class AdaptingFacade : private UtilityProvider
{
public:
  void abstractMethod()
  {
    UtilityProvider::func1();
    UtilityProvider::func2();
  }

  // 'Expose' private methods from
  // Base class.
  //
  using UtilityProvider::func3;
};

/////////////////////////////////////////////////////////////////////
//
int main()
{
  AdaptingFacade adaptingFacade;

  adaptingFacade.abstractMethod();
  adaptingFacade.func1();            // ERROR cannot access private member
  adaptingFacade.func3();            // OK - exposed via 'using'
}

 

As with the Class Adapter pattern we use private inheritance to hide the utility class’s interface and present our own. Again, we can access protected members of the utility class. We can also make use of the using keyword to ‘expose’ private members of the Useful class into the Adapter Facade’s public interface. The method func3(), which was private (because of the private inheritance), has now been made public. This neat facility allows us to present a subset of the original class’s interface without the overhead of a pass-through call.

In summary

Both the Object Adapter pattern and Class Adapter patterns are valid ways of modifying an existing class’s interface to work better in a new environment. The Class Adapter pattern adds the benefit that you can access any protected members of the original class.

The Adapting Façade allows us to modify a class’s interface and also produce a reduced subset of the originals.

In the next article we’ll have a look at memory usage with the adapter patterns.

Polymorphism in C++

May 21st, 2010

The term polymorphism is central to most discussions in and around object oriented design and programming. However I find that many people are still confused or don’t have a complete understanding of the advantages and disadvantages of using polymorphism.

I have heard many different simplified definitions of the root term for polymorphism, usually relating to chemistry or biology. Rather than trying to justify the name, I’ll give you my very simplistic definition from a software perspective.  Simply put polymorphism means:

Multiple functions with the same name.

Yep, as simple as that.

Most C programmers don’t realise they have been using polymorphic operations since they started programming. Take, for example, the following code:

b + c

That’s a polymorphic expression. Why?  Well we know nothing about the types of b and c. If b and c are of type int then the code generated is significantly different to if they are double.

But, I hear to shout, what about virtual functions and all that?

So herein lies on of the main problems. When most people use the term polymorphism they are actually referring to Dynamic Polymorphism. The expression b + c is related to Static Polymorphism.

With static polymorphism, the actual code to run (or the function to call) is known at compile time. C++ Overloading is static polymorphic, e.g.

void swap(int* a, int* b);
void swap(double* a, double *b);
int main()
{
   int x = 10, y = 20;
   double a = 1.2, b = 3.4;
   swap(&x, &y);            // swap(int,int)
   swap(&a, &b);            // swap(double, double)
}

Here the compile, based on the number and type of arguments, can determine which function to call.

Dynamic polymorphism, which in C++ is called Overriding, allows us to determine the actual function method to be executed at run-time rather than compile time.

For example, if we are using the  uC/OS-II RTOS and have developed a Mutex class, e.g.

class uCMutex
{
public:
   uCMutex();
   void lock();
   void unlock();
private:
   OS_EVENT* hSem;
   INT8U err;
   // not implemented
   uCMutex( const uCMutex& copyMe );
   uCMutex& operator=( const uCMutex& rhs );
};

And have also implemented  a very simple stack class (note this code is just for explanation purposes and has many shortcomings) that requires mutual exclusion, it may look something along the flowing lines:

class myStack
{
public:
   myStack();
   bool push(int val);
   int pop();
private:
   static const int sz = 10;
   int m_stack[sz];
   unsigned int count;
   uCMutex tm;   // uCMutex Object
};
myStack::myStack(iMutex& m):count(0), tm(m)
{
   memset(m_stack,0,sizeof(m_stack));
}
bool myStack::push(int val)
{
   bool retval = false;
   tm.lock();    // LOCK
   if (count < sz) {
      m_stack[count++] = val;
      retval = true
   }
   tm.unlock();     // UNLOCK
   return retval;
}
int myStack::pop()
{
   int val = -1;
   tm.lock();       // LOCK
   if (count != 0) {
      val = m_stack[--count];
   }
   tm.unlock();     // UNLOCK
   return val;
}

If, then, in our new design we are going to use VxWorks rather than uC/OS-II, our stack class would require reworking, thus:

class VxMutex
{
public:
   VxMutex();
   void lock();
   void unlock();
private:
   …
};
class myStack
{
private:
   ...
   VxMutex tm;
};

Even though the change from the uC/OS-II mutex to the VxWorks mutex class is within the private part of the stack class, this still has many detrimental knock on effects. Significantly, we have changed the stack class’s definition, so all files that use the stack now need recompiling. This, then, has a knock on effect to the amount of regression testing that is required.

An alternative strategy is to use dynamic polymorphism and interfaces to make our code more testable and reusable.  So, by defining an interface class for the mutex abstraction:

class iMutex
{
public:
   iMutex(){}
   virtual ~iMutex(){}
   virtual void lock() = 0;      // pure virtual function
   virtual void unlock() = 0;    // pure virtual function
private:
   // not implemented
   iMutex( const iMutex&);
   iMutex& operator=( const iMutex&);
};

We can alter the stack code so the mutex object is passed in as a constructor parameter (also the mutex classes require changes to inherit from the iMutex interface):

class uCMutex : public iMutex
{
}
class VxMutex : public iMutex
{
}
class myStack
{
public:
   explicit myStack(iMutex& m);
   bool push(int val);
   int pop();
private:
   static const int sz = 10;
   int m_stack[sz];
   unsigned int count;
   iMutex& tm;   // Mutex Reference
};

Our main code now becomes:

uCMutex ucm;
myStack ms(ucm);

or

VxMutex vxm;
myStack ms(vxm);

This is dynamic polymorphism in operation. Depending on the actual object passed (vxm or ucm), the actual code called when

tm.lock();

is executed, will either be VxMutex::lock() or uCMutex::lock().

Dynamic polymorphism is an incredibly powerful construct and, used well, creates code that can easily be adapted in the face of changing requirements with minimal impact.

However it all comes at a cost. The run-time lookup for virtual functions requires additional code and data. Each dynamic polymorphic class requires a virtual table (v-table), and each object of that type a v-table pointer (vtptr). To call the polymorphic function the run-time system requires indexing into the v-table via the object’s vtptr to actually call the function. In certain environments this can be twice as slow as a normal function call.

So how can we get the benefits of dynamic polymorphism, allowing us to abstract the code from how we’re doing it (e.g. VxWork’s lock call) to what we’re doing (Mutex lock call), but not have to extra overhead of virtual functions.

Well we have C++ templates. So modifying the stack class to become:

template <typename mutex_t>
class myStack
{
public:
   myStack();
   bool push(int val);
   int pop();
private:
   static const int sz = 10;
   int m_stack[sz];
   unsigned int count;
   mutex_t tm;   // Mutex Template Instance
};

and main becomes

 myStack<uCMutex> ms;
 ms.push(10);

With template based code we revert back to static polymorphism from dynamic polymorphism, as the actual call to tm.lock() will be compile time resolved at the possible expense of code readability and complexity.

Finally, I have found that the terms for polymorphism have a number of different names, e.g.

Dynamic Polymorphism

  • Subtype polymorphism
  • Overriding
  • Late binding

Static Polymorphism

  • Parametric polymorphism
  • Overloading
  • Early binding
%d bloggers like this: