在Brew下要实现的功能:在一个IThread线程中读取IWeb中的数据,并进行些后处理。
因为IWeb是异步的方式,如果IWeb下的ISource中无数据,需要在ISource_Readable中注册一个回调函数,当有数据时调用这个回调函数。所以在IThread线程中的业务代码里必须有一个反复判断IWeb中是否有数据的过程。
并且,因为Brew其实是单线程的,所以在IThread中必须调用如下代码,使当前IThread线程加入到Brew的Callback队列中,这样才能响应按键等消息和执行其他的回调函数,避免阻塞对消息循环的访问或者导致界面长事件的不响应。
ISHELL_Resume( pMe->a.m_pIShell,ITHREAD_GetResumeCBK( pMe->pIThread) );
ITHREAD_Suspend( pMe->pIThread );
而ISource对象的Readable函数是用于注册当有数据来时要执行的回调函数,因此理想的状态就是在IThread线程里的循环执行过程中,当IWeb中数据读完后有数据来时,会自动调用注册的回调函数,使整个流程能完整进行下去。
下面是主要数据结构,其中musicspli是Applet的struct,WebAction是IWeb的。
// A WebAction holds state necessary to perform 1 IWeb transaction
typedef struct _musicsplit musicsplit;
typedef struct WebAction
{
musicsplit * pParent; // my parent
AEECallback cb; // how to call me back
IWebResp * piWResp; // the answer I get from IWeb
int nBytes; // count of bytes in response
} WebAction;
struct _musicsplit {
AEEApplet a ;
AEEDeviceInfo DeviceInfo;
.
IWeb* m_pIWeb;
char * m_pszURL; // "URL" field
WebAction m_awa[1];
ISource* m_pISource;
AEECallback m_cbimg;
long read_len;
IThread *pIThread;
IShell *pIShell;
} ;
WebAction也需要有回调函数,在里面获得ISource对象。
static void WebAction_GotResp(void *p)
{
WebAction *pwa = (WebAction *)p;
musicsplit * pApp = pwa->pParent;
WebRespInfo *pwri;
pwri = IWEBRESP_GetInfo(pwa->piWResp);
pApp->m_pISource = pwri->pisMessage;
CALLBACK_Init(&pApp->m_cbimg,imgCallback,pApp);
}
下面是WebAction的初始化函数,初始化URL和回调函数:
static void WebAction_Start(WebAction *pwa, char *pszUrl)
{
musicsplit * pApp = pwa->pParent;
CALLBACK_Init(&pwa->cb, WebAction_GotResp, pwa);
IWEB_GetResponse(pApp->m_pIWeb,
(pApp->m_pIWeb, &pwa->piWResp, &pwa->cb, pszUrl,
WEBOPT_HANDLERDATA, pwa,
WEBOPT_HEADER, "X-Method: GET/r/n",
WEBOPT_END));
}
下面是ISource_Readable传入的回调函数,用于读取数据保存到内存中
static void imgCallback(void * p)
{
int bytesRead;
char *x;
long len = 16384;
musicsplit * pApp = (musicsplit *)p;
x = (char*)MALLOC(len );
bytesRead = ISOURCE_Read(pApp->m_pISource, x, len);
while (bytesRead != ISOURCE_END && bytesRead != ISOURCE_ERROR)
{
if (bytesRead != ISOURCE_WAIT)
{
DBGPRINTF(x);
}
else
{
ISOURCE_Readable(pApp->m_pISource, &pApp->m_cbimg);
return;
}
bytesRead = ISOURCE_Read(pApp->m_pISource, x, 4);
}
}
下面是IThread调用的函数,里面有比较耗时的循环,在循环中会调用挂起线程的函数。经过调试,整个过程还是执行的比较好的,ProcessThread函数能够从当前位置暂停,跳到imgCallback中,imgCallback执行完也能回到ProcessThread刚才暂停的位置。
int ProcessThread(IThread *piThread, void *pvCxt)
{
musicsplit *pMe = (musicsplit *)pvCxt;
long i,j;
double dest,tmp;
char *x;
long len = 16384;
int bytesRead;
// for(i=0;i<10000;i++)
i = 0;
while(i< 10000)
{
x = (char*)MALLOC(len );
bytesRead = ISOURCE_Read(pMe->m_pISource, x, len);
while(bytesRead != ISOURCE_WAIT)
{
pMe->read_len += bytesRead;
bytesRead = ISOURCE_Read(pMe->m_pISource, x, len);
}
while (bytesRead != ISOURCE_END && bytesRead != ISOURCE_ERROR)
{
if (bytesRead != ISOURCE_WAIT)
{
//do some work here
}
else
{
ISOURCE_Readable(pMe->m_pISource, &pMe->m_cbimg);
break;
}
bytesRead = ISOURCE_Read(pMe->m_pISource, x, 4);
}
FREE(x);
for(j=0;j<10000;j++)
{
tmp = FSQRT(i*j);
dest = FPOW(tmp, 4);
DBGPRINTF("===========================%d, %d", i,j);
ISHELL_Resume( pMe->a.m_pIShell, ITHREAD_GetResumeCBK( pMe->pIThread) );
ITHREAD_Suspend( pMe->pIThread );
}
i++;
}
return 1;
}