wireless
Search EarthWeb
CodeGuru | Gamelan | Jars | Wireless | Discussions
Navigate developer.com
Architecture & Design  
Database  
Java
Languages & Tools
Microsoft & .NET
Open Source  
Project Management  
Security  
Techniques  
Voice  
Web Services  
Wireless/Mobile
XML  
Technology Jobs  

   Developer.com Webcasts:
  The Impact of Coding Standards and Code Reviews

  Project Management for the Developer

  Defining Your Own Software Development Methodology

  more Webcasts...




See the Winners!


Developer Jobs

Be a Commerce Partner
Cell Phones
Best Price
Promotional Gifts
Prepaid Phone Card
Imprinted Promotions
Find Software
Online Education
Shop Online
Promotional Pens
Dental Insurance
Promos and Premiums
Car Donations
Compare Prices
Baby Photo Contest

 


Developer News -
Apple's iPhone SDK Off to The Races    March 12, 2008
Sales Data, New Challengers Don't Bode Well For Moto    February 28, 2008
iPhone Grabs Market Share, But Not Yet in The Enterprise    February 6, 2008
Open Wireless Network Looms on Horizon    February 1, 2008
Free Tech Newsletter -

Project Management Guide: Developing a Web Site. Best Practices, Tips and Strategies. Download Exclusive eBook Now.

A Generic Connection Framework for BREW
By Radu Braniste

Go to page: 1  2  3  Next  

Preamble

The article, structured in two parts, tries to establish a common ground for I/O and network operations on BREW and encapsulate this commonality in a framework. Such a framework is used in J2ME to insulate the developer of protocol implementation details, to offer the needed flexibility in supporting new devices and protocols, as well as to define a uniform way of accessing different resources. These reasons are compelling enough to investigate a similar approach for BREW—with an additional challenge: BREW is asynchronous.

First, we will briefly examine the intricacies of the asynchronous programming model and develop some tools to help in our endeavor. As (unfortunately!) there is nothing for free, we'll easily discover that compilers might cruelly dictate the rules of the game. Finding our way in the maze, putting the pieces together, and creating the framework are the fun of the day.

As the final goal is a framework for I/O and network resources handling, we will introduce two simple BREW-specific encapsulations—one for the file manipulation and another one for HTTP—to be used in conjunction with the framework. This is a good opportunity to review some implementations aspects of these interfaces.

Laying the Foundation

BREW is asynchronous by nature—a necessity derived from its design (single threaded, event based, with a watchdog checking the healthy of the system periodically approximately every 60 seconds). This means that otherwise blocking calls are delayed and executed in a non-blocking manner at a later time, control being relinquished after that to a callback function registered at call time (see Command pattern, BeginXXX/EndXXX idiom in .NET, some Observer pattern variants, and so forth).

One example might be derived from the execution of a long, blocking task.

void Caller::executeLengthyOp()
{
  Resource r;
  r.executeTask();
}

This is strictly forbidden in BREW and the famous watchdog might reset the phone. That's why developers have to split the code exceeding the watchdog interval in small chunks, like this:

void Resource::execute()
{
  doOneTimeOperation();
  giveBackControlAsynchronously (&Resource::execute);
  return;    //to main event loop
}

I purposely emphasized the fact that myTaskExecute() has to return control to the main loop (HandleEvent). The interesting part here is giveBackControlAsynchronously (). This method registers (using BREW specific functionality) a callback (in this example re-registers) for later execution or posts an event and quits—an example of non-blocking, asynchronous execution.

Please note this is perfectly valid, too [3]:

void Resource::execute()
{
  giveBackControlAsynchronously (&Resource::execute);
  doOneTimeOperation();
  return;    //to main event loop
}

The above is a user-driven, non-forcing usage pattern (for a complete discussion see [1]).

There is another, system-driven, idiom involving the handling of system resources. ISOCKET_Connect is a good example of a prepackaged asynchronous call. Behind the scenes, it does lots of work and when it finishes it passes you back the result.

ISOCKET_Read works in pair with ISOCKET_Readable like:

int32 rv = ISOCKET_Read(piSock_, buf_, ds_->bufSize);
if  (rv == AEE_NET_WOULDBLOCK) 
{
  ISOCKET_Readable(piSock_, (PFNNOTIFY)P::callbackHandler, &p_);
  doSometingElse();
  return;
}
else ....

The system informs us that a blocking operation is in effect and the only way to continue the reading operation is to register for later processing. What these two last examples have in common is that the system is in control. All tasks involving possible lengthy system resources manipulation should obey this idiom—but regrettably we don't live in a perfect world and exceptions are always possible.

Now, let's concentrate on the mechanics of an async call (forgetting for one moment the infamous watchdog) and make a brief comparison with a synchronous one:

void Resource::executeAsync()
{
  connect();
  return;    //to main event loop
}
void Resource:: connect ()
{
  String data = connectAndGetData ();
  if (data.isEmpty()
  {
    register (&Resource::connect) ;
  }
  else
  {
    useData(data);
  }
  return;    //to main event loop
}

versus:

void Resource::executeSync()
{
  String data = connectAndGetData ();
  useData(data);
  return;    //to main event loop
}

What we can immediately observe is the fragmentation of the code logic in the async version—scattered now in two functions. The second observation is that useData() has nothing to do with Resource class and it should be injected by the caller in the Resource space. And, finally, the third observation is that conectAndGetData() has to preserve the state between calls—and as in BREW static or global data are absolutely forbidden the only way to do it is to encapsulate the data in MyClass. The RAII—Resource Acquisition Is Initialization [2]—idiom seems to be the natural choice:

typedef void (Caller::*FND)(  );
class ResourceHandle
{
  ResourceHandle (FND f) : f_(f)
  {connect();}
  ~ ResourceHandle ()
  { releaseResources();  }

private:
  ResourceHandle (const ResourceHandle &);
  void operator=(const ResourceHandle &);
  String connectAndGetData();
  FND f_;
  void releaseResources;    //cancels the callback
  //"static" data used by connectAndGetData(), for example:
  String buffer_;
};

Usage:

void Caller::someFunction()
{
  ResourceHandle rh(&Caller::useData);
}

Nice, but pointless—rh is destroyed at the end of the someFunction() body and the callback is never called. A better method would be:

void Caller::someFunction()
{
  ResourceHandle * rh = new ResourceHandle(&Caller::useData);
}

We have now a behavior similar to the synchronous case, but with an extra problem—finding a way to delete rh to avoid a memory leak. There are two options:

  1. Make rh a private member of Caller—with the disadvantage that Caller has to keep track of ResourceHandle (and maybe other handles of other types).
  2. Create a central Handle repository that keeps track of the myriad of resources that might be used in the lifespan of the application. This looks more promising because all we have to keep track of in this case is the repository itself, once per application.

Now that we know how to deal with resources, let's go a little bit deeper—the callback registration mechanism level, namely. Because BREW is a C-based environment, it uses C functions for callbacks, passing the state through an opaque void* pointer. This usually translates into the following C++ idiom:

void Resource:: connectImpl ()
{
  register (&Resource::connect, this) ;
}

static void Resource:: connect (Resource * r)
{
  r->connectImpl();
}

There is an elegant way to get rid of the static method and use C++ callbacks:

void Resource:: connect ()
{
  p_.setCallback((&Resource::connect, this);
  register (&P::callbackHandler, &p_) ;
}

The mysterious P is actually an adapter, like:

template <class Y, class F>
struct pkCBK0
{
  void setCallback(Y* y, F fx)
  {
    y_ = y;
    f_ = fx;
  }
  static void callbackHandler(void* v)
  {
    typedef pkCBK0<Y,F> pk;
    pk* z = static_cast<pk*>(v);
    F fx = z->f_;
    Y* y = z->y_;
    (*y.*fx)();
  }
  Y* y_;
  F f_;
};

The implementation takes advantage of the void* pointer—passing both the real instance (the original "this") as well as the method address in the same void*. There is a downside, of course; p_ has to be a member of Resource as p_ is now the "state keeper." For a resource, this is not a problem—because a resource is essentially an encapsulation. The interesting case is when a P callback has to be used by a Caller. The solution at rescue might be again the central repository, as we'll see shortly.

Go to page: 1  2  3  Next  

Next article: A GCF for BREW: Working with File I/O & Network Resources


Tools:
Add www.developer.com to your favorites
Add www.developer.com to your browser search box
IE 7 | Firefox 2.0 | Firefox 1.5.x
Receive news via our XML/RSS feed


BREW Archives

Intel Go Parallel Portal: Translating Multicore Power into Application Performance
Best Practices for Developing a Web Site. Checklists, Tips & Strategies. Download Exclusive eBook Now.
Developing Intelligent Communications? Visit the Avaya DevConnect Center on DevX.
Whitepaper: Embeddable Content Platform for OEM's
Whitepaper: XML Processing in Applications--Take the Next Step



JupiterOnlineMedia

internet.comearthweb.comDevx.commediabistro.comGraphics.com

Search:

Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

Jupitermedia Corporate Info


Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

Solutions
Whitepapers and eBooks
Microsoft Article: HyperV-The Killer Feature in WinServer ‘08
Avaya Article: How to Feed Data into the Avaya Event Processor
Microsoft Article: Install What You Need with Win Server ‘08
HP eBook: Putting the Green into IT
Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
Avaya Article: Setting Up a SIP A/S Development Environment
IBM Article: How Cool Is Your Data Center?
Microsoft Article: Managing Virtual Machines with Microsoft System Center
HP eBook: Storage Networking , Part 1
Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
MORE WHITEPAPERS, EBOOKS, AND ARTICLES
Webcasts
Intel Video: Are Multi-core Processors Here to Stay?
On-Demand Webcast: Five Virtualization Trends to Watch
HP Video: Page Cost Calculator
Intel Video: APIs for Parallel Programming
HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
MORE WEBCASTS, PODCASTS, AND VIDEOS
Downloads and eKits
Sun Download: Solaris 8 Migration Assistant
Sybase Download: SQL Anywhere Developer Edition
Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
Red Gate Download: SQL Compare Pro 6
Iron Speed Designer Application Generator
MORE DOWNLOADS, EKITS, AND FREE TRIALS
Tutorials and Demos
How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
IBM Article: Collaborating in the High-Performance Workplace
HP Demo: StorageWorks EVA4400
Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
Microsoft How-to Article: Get Going with Silverlight and Windows Live
MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES