October 31, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

A Generic Connection Framework for BREW

  • July 30, 2003
  • By Radu Braniste
  • Send Email »
  • More Articles »

Putting the Pieces Together

Till now we've collected the following requirements:

  1. A central repository capable of hosting a non-homogeneous collection of different instances has to be in place.
  2. Every resource will be encapsulated as per RAII.
  3. Every resource encapsulation manages its associated callbacks.

As our main goal is to access resources generically. It looks like a good idea to mediate resource maneuvering, meaning that:

  1. Caller will use Resources via a Mediator.
  2. Mediator is responsible for proper resource handling (including creation/destruction).
Note: The basic role of the Mediator is a separation of concerns. Minimal implementations might not implement it at all.

Implementation

Central Repository is implemented in the ResourceRegistry class as a homogeneous collection of polymorphic instances—meaning we need to define a specialized interface to be implemented by all the elements:

class IRelease
{
public:
  virtual void releaseResource() = 0;
  virtual int getUID() = 0;
protected:
  IRelease(){};
  virtual ~IRelease() {};
private:
  IRelease( const IRelease &value );
  const IRelease &operator = ( const IRelease &rhs );
};

Destructor is private because objects implementing this interface cannot be created on the stack. ResourceRegistry has a simple interface:

class ResourceRegistry
{
public:
  void registerResource(IRelease* resource);
  bool unregisterResource(IRelease* resource);
  IRelease* getRegistered(int uid) const;
  ~ResourceRegistry() ;
  ResourceRegistry(int swapLimit):swapLimit_(swapLimit)
  {}
private:
  void unregisterResources();
  void swap();
private:
  BrewVector<IRelease*> resources_;
  int swapLimit_;

private:
  ResourceRegistry( const ResourceRegistry &value );
  const ResourceRegistry &operator =(const ResourceRegistry &rhs);
};

The objects stored inside the repository can be differentiated by a unique, type dependent, ID. That's why getRegistered takes an int parameter. In the meantime, Resources can be reusable or not—and this can be set via a policy class.

The Mediator is implemented in:

template <class P, class T, class U, class W, class R = ResourceRegistry>
class CbkDispatcher : public IRelease, IExecute
{
public:
  virtual void onCbk( ) ;
  virtual void releaseResource( ;
  virtual int getUID( ) ;
  static int getID();
  static int getDispatcher(IShell* shell, R*  r, P& p, W* w);
private:
  CbkDispatcher( IShell* shell, R*  r, P& p;
  ~CbkDispatcher();
  void releaseResources();
  void releasePipe();
  void close() const;
  int initRequest(W* w) ;
private:
  IShell* shell_;
  U* u_;
  P& p_;
  R* r_;
private:
  CbkDispatcher( const CbkDispatcher &Value );
  const CbkDispatcher &operator = ( const CbkDispatcher &Rhs );
  CbkDispatcher(){};
};

The lifetime of a resource can be expressed in the sequence:

  1. initRequest is called by getDispatcher() on behalf of a Caller. As mentioned before, CbkDispatcher is a proxy for the Resource. Caller passes all the needed information, including the output buffer[s] and an asynchronous callback of type P—(p_).
  2. Resource is internally initialized, an internal async method is called and the control returns to Caller.
  3. Resource executes asynchronously.
  4. At the end, p_ is executed asynchronously and CbkDispatcher "commits suicide" or is returned into the ResourceRegistry pool depending on the policy.

CbkDispatcher uses a policy defining whether the associated resources should be treated as reusable or not.

CbkDispatcher accepts a puzzling parameter of type W. This is the data to be passed to the Resource and is an opaque structure implementing IRelease (so it can be hosted in ResourceRegistry as well). W is a different type for every Resource (as it encapsulates specific properties). W has to expose at least two fields—address and parameters—and two methods:

static int getID();
template <class R>
static GDS* initDataStruct(R* rr, char* address,
                           const String& params );

A generic resource is a class exposing three methods:

int     init();
int     initConnection();
void    reset();

There are two initialization methods because a resource is constructed in two steps (more on this when dealing with networking resources). A resource might be reusable. That's why we need a way to reset() it.





Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel