Sunday, April 11, 2010

Backdoor C++ Idiom - part II

After having see the motivation, let us now turn to generic problem and solution.

Context and Applicability
  • You are designing a class using a language such as C++, which provides public, protected and private access rights, constructor and destructor and in which friend classes can be declared.
  • The class offers some services that must be used with caution following a given protocol. If the guaranties are not ensured your system will crash.
  • This protocol can be ensured by third classes in multiple ways not know in advance by the class designer.
Problem

The class you are designing offers some services that must be used with caution following a given protocol, e.g. opened files must be closed, acquired mutex must be released, opened transaction must be suspended, committed or rolled back, suspended transaction must be resumed, or rolled back, resumed transactions must be suspended, committed or rolled back.
The program must be designed carefully to avoid these non-conformances. These errors aren't rare or exotic failures - they are virtually guaranteed to occur unless the interface is designed to avoid them.
Giving a public access would be dangerous, delegating to the client the responsibility to ensure a correct usage. Giving a private access to this services would force to declare the friend classes that are able to use this interface, while the class name and number which can correctly use this services are not known in advance.

Solution

Differentiate between two kinds of clients for your class:
  • Aware clients that are aware of the protocol constraints in order to construct safe interfaces adapter and
  • Unaware clients which use safe interfaces and which can be unaware of the protocol constraints.

Define a backdoor access to your class that acts as a bridge to your class. Allows friend access to the backdoor class.
Aware clients use the public interface and the back-door one with caution in order to respect the protocol constraints.
Unaware clients use the safe public interface and the Safe adapters.

Structure and Participants

The participants in the Backdoor idiom include the following:
Component: grants access to the BackdoorComponent
ComponentBackdoor: defines a restricted public interface to the private part of a component, which must be used with caution, and a protected one for the derived component backdoors.
ComponentSafeAdapter: Provides a safe mean for using the concept ensuring that the component protocol constraints are respected. ComponentSafeAdapter objects are constructed with a reference to a component object and use the ComponentBackdoor class aware of the protocol constraints. This class follows the RAII C++ idiom to ensure that on destruction the component instance is left on a stable state. A variant can be to left on an unstable state but be sure that the safety has been transferred before destruction to another object.
UnawareClient: uses the public interface of Component as well as the ComponentSafeAdapters.


Consequences
Benefits
  • The unsafe use has been limited to the aware component safe adapters.
  • The unaware client cannot use unsafe features and is guided by the component safe adapters.

Liabilities
  • The design is more complex, we have in addition to the component, a component back-door and several component safe adapters.
  • The backdoor interface must be designed carefully to open only the needed private services that help the component safe adapters design.
  • Modifications on the class interface may be synchronized on the backdoor interface.
  • The component designer can document and why not define helper “typedef” for the component safe adapters it knows the time the component is designed, but the other component safe adapters cannot be associated to the Component using the C++ language.
  • It is not possible with the C++ type system to know which clients are aware or not. Is the client using the backdoor interface which must be conscientious of its awareness in order to define a safe usage of the component ? One hint that could guide the client to know if it can use the backdoor interface would be to answer the question, “can this class be considered as an extension of the component interface, i.e. is a component safe adapter?”
Next part will concentrate on possible implementations in C++.

Wednesday, April 7, 2010

Backdoor C++ Idiom - part I

Intent

Provide a safe interface to a class that ensures its internal guaranties without closing too much the class interface.

Motivation

Designing a C++ concurrent library can be done in a simple way by defining a wrapper of the types, constants, and functions of an existing C thread library. For example the class mutex is used to ensure mutually exclusive access to data.
class mutex {
public:
// … 
  void lock();
  void unlock();
// … 
};
While the C++ wrapper interface can eliminate some of the C liabilities, it doesn't avoid the fact that client must master the protocol usage: the client must guarantee that the unlock function is called each time the lock function is called.
{
  mtx.lock();
  // … [a]
  // not called if an exception occurs in [a] 
  mtx.unlock();
}
A first step forward could consist in using the C++ scoped idiom (RAII) to define some scoped classes that will acquire the mutex on construction and release it on destruction.
class  mutex_strict_lock {
public :
  mutex_strict_lock(mutex& mtx) : mtx_(mtx) {
    mtx_.lock();
  }
  ~mutex_strict_lock(mutex&) {
    mtx_.unlock();
  }
private :
  mutex mtx_;
};
and use it in a scoped block:
{
  mutex_strict_lock guard(mutex);
  // … 
  // destructor called when exit from this block 
  // even on exception
}
While this reduces risk, it does not force the client to only use this safe mechanism in order to lock/unlock a mutex, since the lock and unlock functions remain public.
A second step could be to declare the lock/unlock functions private and to grant friend access to the mutex_strict_lock class.
class  mutex {
public:
  // ...
private:
  // … 
  void lock();
  void unlock();
  // … 
  friend class  mutex_strict_lock;
  // ...
};
Now the following code does not compiles
{
  mtx.lock(); // ERROR do not compile 
  // .. [a] 
  // not called if an exception occurs in [a]
  mtx.unlock();// ERROR do not compile
}
This ensures a safe use of the class but there is no other way to use a mutex, the interface to the mutex class is now close. Once the mutex is locked, it cannot be unlocked neither relocked as many times as the client considers pertinent. A close interface is less useful than an unsafe one.
The main problem with the mutex_strict_lock class is that even if it ensures the mutex guaranties, it adds another one; the mutex stays locked during the lifetime of the mutex_strict_lock instance. Moreover, the safe adapter must ensure the guaranties but not limit the initial set of functionalities. Sometimes this can be done with a single safe adapter class or with a set of safe adapters classes. So the designer of the class must define at least a minimal set of safe adapters that covers the whole set of functionalities. In the case of the mutex class, a mutex_scoped_lock can ensure the guaranties and satisfy all the functionalities.
Once we have a minimal set of safe adapters, the designer can find some other interesting usages of its class, which could in addition ensure other guaranties, and then grant friend access to all this classes.
class  mutex {
  // ... 
  friend class  mutex_scoped_lock;
  friend class  mutex_strict_lock;
  friend class  mutex_scoped_reverse_lock;
  //...
};
This could seems good, but the library designer can not pretend to know in advance all the safe usages of its library while each of the safe adapters needs to access the lock/unlock functions. There are other ways to ensure the guaranties, as a mutex_locking_ptr, mutex_scoped_locking_ptr, and surely many others. But now we cannot use these new safe classes without modifying the initial class.
What we are looking for is not to limit the safe usage of the initial class, but just to protect from unsafe usages. The idea is to define a two levels interface for a class, one being safe while the other is unsafe but only visible to safe aware clients. Evidently there is no means to check this safety awareness, but the fact the interface is split in two interfaces having different usages, helps the unaware client to identify the safe interface, and signals to the client that using the unsafe interface s/he must be aware of the unsafe features.

More coming soon, stay tunned.

Friday, April 2, 2010

Pimpl Static Variant

In a already old article "The Joy of Pimpls (or, More About the Compiler-Firewall Idiom)", Herbe Sutter states
There are four main alternative disciplines:
  • Put all private data (but not functions) into XImpl.
  • Put all private members into XImpl.
  • Put all private and protected members into XImpl.
  • Make XImpl entirely the class that X would have been, and write X as only the public interface made up entirely of simple forwarding functions (another handle/body variant).
My experience is that in some contexts we could add more private member functions than private member data. For example, when we apply the pattern "Methods for States - A Pattern for Realizing Object Lifecycles" from Kevlin Henney, we have a lot of internal function to represent transitions between states. A change in the implementation of the FSM means adding or removing transition. If these internal functions are declared at the class level, we need to modifying the header file.

I have explored a different variant
  • Put all private functions and static data (but not instance data) into XImpl. XImpl needs only to store the back pointer.
This variant avoid changing the header file in those cases. I will adapt the clock example from "Methods for States" to show how the variant works.
// clock.hpp
class clock {
public:
void change_mode() {
 (this->*(behavior->change_mode))();
}
void increment() {
  (this->*(behavior->increment))();
}
void tick() {
  (this->*(behavior->tick))();
}
private:
  typedef void (clock::*function)();
  struct mode {
    const function change_mode, increment, tick;
  };
  static const mode displaying_time
  static const mode setting_hours;
  static const mode setting_minutes;
  const mode *behavior;
  int hour, minute, second;

  template<const mode *next_mode>
  void change_to() {
behavior = next_mode;
  }
  void next_hour() {
hour = (hour + 1) % 24;
  }
  void next_minute() {
minute = (minute + 1) % 60;
  }
  void update_time() {
if(++second == 60) {
second = 0;
if(++minute == 60) {
minute = 0;
hour = (hour + 1) % 24;
    }
    }
  }
  void do_nothing() {}
};

// clock.cpp
const clock::mode clock::displaying_time = {
  &clock::change_to<&setting_hours>, 
&clock::do_nothing, 
&clock::update_time
};
const clock::mode clock::setting_hours = {
  &clock::change_to<&setting_minutes>, 
&clock::next_hour, 
&clock::do_nothing
};
const clock::mode clock::setting_minutes = {
  &clock::change_to<&displaying_time>, 
&clock::next_minute, 
&clock::do_nothing
};
Hiding internal functions and static data in the header file
Only the public interface, the private instance data and the grant friendship to impl appear on the header file.
// clock.hpp
class clock {
public:
  void change_mode();
  void increment();
  void tick();
private:
  struct impl; // forward declaration
  friend class impl;

  struct mode; // forward declaration
  const mode *behavior;
  int hour, minute, second;
};
Moving to the implementation file the private part
The types used only by the implementation go to the implementation file clock.cpp.
// clock.cpp
typedef void (clock::impl::*function)();
struct clock::mode {
  const function change_mode, increment, tick;
};
The class implementation follows always the same schema.
  • Define a variable referencing the class to implement, and
  • a constructor taking an instance of this class.
struct clock::impl {
clock& that;
impl(clock* thisClock) : that(*thisClock) {}
  ...
};
Next follows the private static data:
struct clock::impl {
  ...
  static const clock::mode displaying_time;
static const clock::mode setting_hours;
  static const clock::mode setting_minutes;
  ...
};
And the functions that were private
struct clock::impl {
  ...
  template<const clock::mode *next_mode>
  void change_to() {
that.behavior = next_mode;
  }
  void next_hour() {
that.hour = (that.hour + 1) % 24;
  }
  void next_minute() {
that.minute = (that.minute + 1) % 60;
  }
  void update_time() {
  if(++that.second == 60) {
that.second = 0;
     if(++that.minute == 60) {
that.minute = 0;
that.hour = (that.hour + 1) % 24;
     }
    }
  }
  void do_nothing() {}
};
The definition of the public functions need just to replace this-> by impl(this).
void clock::change_mode() {
 (impl(this).*(behavior->change_mode))();
}
void clock::increment() {
 (impl(this).*(behavior->increment))();
}
void clock::tick() {
 (impl(this).*(behavior->tick))();
}
Last, the static initialization is done.
const clock::mode clock::impl::displaying_time = {
  &clock::impl::change_to<&setting_hours>,
&clock::impl::do_nothing,
&clock::impl::update_time
};
const clock::mode clock::impl::setting_hours = {
  &clock::impl::change_to<&setting_minutes>,
&clock::impl::next_hour,
&clock::impl::do_nothing
};
const clock::mode clock::impl::setting_minutes = {
  &clock::impl::change_to<&displaying_time>,
&clock::impl::next_minute,
&clock::impl::do_nothing
};
While this approach doesn't encapsulates all the private members, it has some advantages:
  • The XImpl class has no inherent instance data, so no space overhead
  • The class doesn't needs to store any XImpl pointer as there is no data to maintain, so no need to allocate/deallocate it.
  • Reduce the performance overhead of the Pimpl idiom.
The drawbacks are:
  • Need to include the headers declaring the private instance data types.
  • There is yet a minimal performance overhead on the construction of the temporary XImpl class and the dereference of the back pointer.