您的位置:首页 > 其它

ACE中对线程的封装

2015-11-20 13:35 357 查看
1.ACE中对线程的封装

1.1ACE_Thread实现原理

ACE_Thread 提供了对OS 的线程调用的简单包装,这些调用处理线程创建、挂起、取消和删除等问题。它提供给应用程序员一个简单易用的接口,可以在不同的线程API 间移植。ACE_Thread 是非常“瘦”的包装,有着很少的开销。其大多数方法都是内联的,因而等价于对底层OS 专有线程接口的直接调用。ACE_Thread 中的所有方法都是静态的,而且该类一般不进行实例化。

ACE_Thread类中的几个重要的静态函数:

1)建立线程:

size_t spawn_n (size_t n,

ACE_THR_FUNC func,

void *arg = 0,

long flags = THR_NEW_LWP | THR_JOINABLE,

long priority = ACE_DEFAULT_THREAD_PRIORITY,

void *stack[] = 0,

size_t stack_size[] = 0,

ACE_Thread_Adapter *thread_adapter = 0)

{



for (i = 0; i < n; i++)

// Bail out if error occurs.

if (ACE_OS::thr_create (func,

arg,

flags,

&t_id,

0,

priority,

stack == 0 ? 0 : stack[i],

stack_size == 0 ? 0 : stack_size[i],

thread_adapter) != 0)

break;

return i;

}

该函数可以同时创建n个线程。该函数在中途遇到创建线程失败的情况出现时会自动跳出,而不继续创建。

size_t ACE_Thread::spawn_n (ACE_thread_t thread_ids[],

size_t n,

ACE_THR_FUNC func,

void *arg,

long flags,

long priority,

void *stack[],

size_t stack_size[],

ACE_hthread_t thread_handles[],

ACE_Thread_Adapter *thread_adapter)

该函数可以使用thread_ids[]记录所有创建成功的线程的id号。

而对于spawn函数则只能够创建单个线程。

1.2ACE_Task_Base实现原理

ACE_Task_Base 是ACE 中的任务或主动对象“处理结构”的基类。在ACE 中使用了此类来实现主动对象模式。所有希望成为“主动对象”的对象都必须从此类派生。你也可以把ACE_TASK 看作是更高级的、更为面向对象的线程类。

ACE_Task_Base调用时必须重写svc方法,并且在使用时保证调用了activate方法。

最常见的使用流程如下例:

class TaskOne: public ACE_Task_Base

{

public:

//Implement the Service Initialization and Termination methods

int open(void*)

{

activate();

return 0;

}

int close(u_long)

{

return 0;

}

int svc(void)

{

// do thread specific work here

//.......

//.......

return 0;

}

};

int main(int argc, char *argv[])

{

//Create the task

TaskOne *one=new TaskOne;

//Start up the task

one->open(0);

//wait for all the tasks to exit

ACE_Thread_Manager::instance()->wait();

ACE_DEBUG((LM_DEBUG,"(%t) Main Task ends \n"));

}

ACE_Task_Base中的关键方法:

①open

用户改写该函数,在其中调用ACE_Tase_Base::activate()方法。

②svc

用户必须重新实现该方法,用于供线程调用。

③close

用户可以修改该函数用于完成在线程结束前的清理工作。

④svc_run

该方法为静态函数,作为线程的回调函数。该函数中调用了svc方法。这里有一个技巧ACE_Task_Base在实现svc_run函数时将ACE_Task_Base类的对象以参数形式传进了svc_run方法中:

ACE_Task_Base::activate(…)

{



//第三个参数为传入回调函数的参数指针。

this->thr_mgr_->spawn_n (n_threads,

&ACE_Task_Base::svc_run,

(void *) this,

flags,

priority,

grp_id,

task,

thread_handles,

stack,

stack_size);



}

ACE_Task_Base::svc_run (void *args)

{



ACE_Task_Base *t = (ACE_Task_Base *) args;



// Call the Task's svc() hook method.

int svc_status = t->svc ();



}

1.3ACE_Thread_Adapter实现原理

在说明ACE_Thread_Adapter类的实现原理之前我们首先要明白该类有什么用,被用在哪里。从后缀的Adapter可以猜测该类属于适配器类,而在设计模式中适配器设计模式往往是用来转换接口而用。

1.4 ACE_Thread_Manager实现原理

ACE_Thread_Descriptor类的对象存放程序的描述信息。

ACE_Thread_Manager的实现原理简单概括起来就是:将需要管理的线程的线程信息保存在特定的双向链表中,以供需要操作线程时使用。

将线程加入管理类的方法有两种:

1)使用ACE_Thread_Manager的spawn系列方法启动线程后会自动加入到ACE_Thread_Manager管理的线程双向链表中。

2)直接使用ACE_Thread_Manager的insert_thr方法直接将已启动的线程加入到ACE_Thread_Manager管理的线程双向链表中。

※注释:

不管使用上面那种方法,最终都需要调用append_thr方法将线程信息类ACE_Thread_Descriptor的对象插入到ACE_Double_Linked_List thr_list_信息双向链表中。

使用ACE_Thread_Manager的spawn系列方法最终都会调用spawn_i方法来启动线程,spawn_i方法实现过程中发生了几个关键的调用:

ACE_Thread::spawn (…) 启动线程

append_thr(…) 将线程信息插入到双向链表thr_list的尾端。

ACE_Thread_Manager类中对于所管理的线程对象的查找以及操作等都是同过ACE_Thread_Descriptor对象作为参数进行操作的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: