Refactoring Synchronous Interfaces
Most of us come from a background where synchronous interfaces are the norm: as a developer, you call a function and wait for the results. If you're doing something with an external resource (say, the network), your application stops executing and other things happen until the remote resource provides the data I need. Not so in BREW, which is an asynchronous, cooperatively-multitasked environment. In BREW, rather than wait for an external event to occur, you register a callback that the system will invoke when the event has actually happened. For example, to read on a socket, you might write:
Static int SomeSetupFunction (CApp *pMe)
// Now that our socket's created, wait for data
ISOCKET_Readble( pMe->pISocket, (PFNNOTIFY)DoRead, pMe );
static void DoRead(CApp *pMe)
n = ISOCKET_Read( pMe->pISocket, pMe->buffer, BSIZE );
if ( n > 0 ) ProcessData( pMe );
} while( n>0);
if ( EWOULDBLOCK == n )
// Wait for another round…
ISOCKET_Readable( pMe->pISocket, (PNNOTIFY)DoRead, pMe );
// Handle the error
HandleNetError( pMe );
This code asks the ISocket interface to notify you when data's available for reading; once there's data available, you loop to read the available data until either an error occurs or there's no more data to be read. If there’s no more data, simply ask the socket to notify you again when more data is available.
Unfortunately, moving from synchronous to asynchronous events is hard. You're going to need to re-write your code, keeping in mind that it's your application's responsibility to share the processor with the rest of the system. One BREW interface that can help you do this is IThread, which lets you set up a cooperative thread of execution in your application. Using IThread, you specify a function to execute, which should relinquish the processor at regular intervals using ITHREAD_Suspend. You must schedule the thread's resumption by registering a callback and using ISHELL_Resume; the mechanism essentially gives you an easy way to encapsulate a chain of callbacks and an associated heap. While using IThread doesn't solve the fundamental problem for you, it at least provides a framework in which to work, so that you don't need to write a state machine from scratch.