Chinaunix首页 | 论坛 | 博客
  • 博客访问: 637114
  • 博文数量: 116
  • 博客积分: 6078
  • 博客等级: 准将
  • 技术积分: 1214
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-23 10:09
文章分类

全部博文(116)

文章存档

2016年(1)

2015年(4)

2011年(2)

2010年(21)

2009年(88)

分类: C/C++

2009-06-18 14:26:27

永远活在同步的流程里,无疑是我等码工最大的奢望之一。为了不阻塞UI,为了读写一陀陀数据,为了含辛茹苦的演算复杂的逻辑,为了大家和睦相处共同劳动, 总是需要异步处理,你一下我一下共同完成任务。在Symbian中,做了一套机制来做这件事情,这就是Active Objects。

Active Objects

Active Object是一套事件驱动的多任务模型。在Symbian的标准线程中(除掉一些Java构造线程、原生C构造线程,等),都包含有一个消息循环,在循 环中,会不停的查询注册在该线程所属的CActiveScheduler各个ActiveObject的TRequestStatus状态,一旦发现可执 行的任务,立马激活并执行。经典的循环伪码如下:


// *** in the loop ***

User::WaitForAnyRequest();

FOREVER
    {
    if(activeObject->IsActive()  && activeObject->iStatus != KRequestPending)
        {
        activeObject->iActive = EFalse;
        TRAPD(r, activeObject->RunL());
        if( r != KErrNone )
            {
            r = activeObject->RunError();
            if( r != KErrNone )
                Error(r);
            }
        break;
        }
    }



一 码解千语。在消息循环中,会等待事件激活,接着,会遍历查询注册各个Active Object的状态。当然,简单的遍历是不够体面的,每个Active Object都是带着优先级来的,毫无疑问,优先级高的会被优先考虑执行,低的永远也超越不了。默认,大家都使用EPriorityStandard,一 切太平。如果,一个Active Object是需要长时间被执行的,可以考虑使用低优先级,EPriorityIdle、EPriorityLow,这样执行的频率会低一些。而如果任务 是具有一些实时要求的,就需要使用高的优先级,亦如,EPriorityUserInput、EPriorityHigh。

但这个模型, 是不足够满足实时要求的,因为它是非抢占式的。一个低优先级的任务,被调度了,在那里磨叽磨叽,你优先级再高也奈何不了。在这种模式下,要保持良好的响应 能力,需要自律。首先,如果一个任务的实时性高,那么就需要调高它执行线程或进程的优先级,让它优先被CPU调度,不给低优先级任务执行的机会。还有,就 是不要在Active Object的RunL中放置执行效率低下的代码(如果是非主线程,那就看菜下饭了...),它会使得该线程失去响应其他请求的能力。

每个异步的任务,都需要派生自CActive类。如果用系统向导,可以发现,Symbian希望每个CActive的子类,做以下几件事情:
  • 实现RunL,放置等待回调一方的执行代码;
  • 实现DoCancel方法,把未有机会到达目的地的任务妥善安置,这是一个模板方法模式,它会被放在Cancel,仅在状态为执行时,会被调用;
  • 实现RunError,在执行出错后,给该CActive子类一次自我救赎的机会;
  • 尝试告诉使用者,这世界没有免费的午餐,需要用SetActive将请求发送给那个执行者,让它帮你搞定问题。

任 务驱动的控制核心在于TRequestStatus,执行一方在接到任务后,会将TRequestStatus设置成为KRequestPending, 当这个状态被再次改变了,才会触发CActiveScheduler调度执行回调。
Client-Server框架

Client- Server框架,是Symbian的重要机制。在Symbian的内核层面,大量使用该模式,将文件管理,界面管理等功能都剥离到了各个服务中,呈微内 核态势。所谓Client-Server框架,就是功能调用者Client,和功能执行者Server,各据一方,处于不同的线程或进程。它们搭建在 Active Object上,通常通过异步模式进行调用。不过,Client-Server并没有对执行模式进行约束,比如文件服务,就具有同步和异步两种调用模式, 当然,本质上换汤不换药,所谓同步只是阻塞异步来实现的。

Client-Server分同进程和跨进程两种,不用说,通信模式完全不一 样。在跨进程模式下,需要通信,就需要在Client和Server之间建立一个Session。Session是对Symbian IPC的封装,用协定方式进行通信,只不过,大数据的传输还需要各行其道各显神通。而同进程下,传递信息就简单多了,很多时候,同用一个指针就好。在跨进 程模式下,适合集中控制,统一管理资源,特适合想文件服务这样的东东。而同进程,则适合大数据的传输,和逻辑的运算,各开各的线程,各跑各的逻辑。
阅读(1127) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

lihao_nx2009-06-19 13:56:23

是的,ActiveScheduler可以看作是把AO集合成一个线程内顺序执行的序列,而为了使用相关资源则用信号来同步

fera2009-06-19 10:50:28

消息循环不是线程的,而是ActiveScheduler的;也不是不停的查询,而是通过semaphore来同步。你的伪代码User::WaitForAnyRequest();也是这么说的。因此,不是由TRequestStatus被修改来触发RunL()调用。