对象容器的实现

Posted 旭日初扬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了对象容器的实现相关的知识,希望对你有一定的参考价值。

一、简介

1.1、什么是对象

在RT-thread中所有的数据结构都是对象。

1.2、什么是容器

  • 存放对象(线程)的地方叫容器。
  • 目的:RT-Thread 的组件 finsh 通过扫描容器的内核 对象来获取各个内核对象的状态,然后输出调试信息。 

二、实现

2.1、对象枚举定义

*线程,信号量,互斥量、事件、邮箱、消息队列、内存堆、内存池、设 备和定时器的枚举定义
即为每个对象打上了一个数字标 签,具体代码如下。 */

enum rt_object_class_type

    RT_Object_Class_Thread = 0, //  对象是线程
    RT_Object_Class_Semphore,   //  对象是信号量
    RT_Object_Class_Mutex,      //  对象是互斥量
    RT_Object_Class_Event,      //  对象是事件
    RT_Object_Class_MailBox,    //  对象是邮箱
    RT_Object_MessageQueue,     //  对象是消息队列
    RT_Objece_Class_MemHeap,    // 对象是内存堆
    RT_Object_Class_MemPool,    //  对象是内存池
    RT_Object_Clasee_Device,    //  对象是设备
    RT_Object_Class_Timer,      //  对象是定时器
    RT_Object_Class_Module,     //  对象是模块
    RT_Object_Class_Unknown,    // 对象未知
    RT_Object_Class_Static,     //  对象是静态对象
;

/  C 语言知识:如果枚举类型的成员值没有具体指定,那么后一 个值是在前一个成员值的基础上加 1。
enum rt_object_info_type

    RT_Object_info_Thread = 0, //  对象是线程

#ifdef RT_USIGN_SEMAPHORE
    RT_Object_Info_Semaphore,  //  对象是信号量
#endif

#ifdef RT_USIGN_EVENT          //  对象是事件
      RT_Object_Info_Event,
#endif
	
#ifdef RT_USING_MUTEX
    RT_Object_Info_Mutex,       //  对象是互斥量
#endif

#ifdef RT_USIGN_MAILBOX
    RT_Object_Info_mailBox,      // 对象是邮箱
#endif

#ifdef RT_USING_MESSAGEQUEUE
    RT_Object_Info_MessageQueue, //  对象是消息队列
#endif

#ifdef RT_USING_MEMHEAP
    RT_Object_Info_MemHeap,       /* 对象是内存堆 */
#endif
#ifdef RT_USING_MEMPOOL
    RT_Object_Info_MemPool,      /* 对象是内存池 */
#endif
#ifdef RT_USING_DEVICE
    RT_Object_Info_Device,       /* 对象是设备 */
#endif

    RT_Object_Info_Timer,        /* 对象是定时器 */

#ifdef RT_USING_MODULE
    RT_Object_Info_Module,       /* 对象是模块 */
#endif

    RT_Object_Info_Unknown, /* 对象未知 */
;

2.2、对象数据类型定义

/*内核对象的基础数据结构
线程控制块中添加数据
*/
struct rt_object

    char name[RT_NAME_MAX]; //  定义在config.h  默认8
    rt_uint8_t type;        //  对象类型
    rt_uint8_t flags;       //  对象状态
    rt_list_t list;         //  对象的列表节点  挂载在什么容器中
    rt_list_t tlist;        //  线程节点列表
	
    void *sp;               //  线程栈指针
    void *entry;            //  线程入口地址
    void *parameter;        //  线程形参
    void *stack_addr;       //  线程起始地址
    rt_uint32_t stack_size; //  线程栈大小,单位字节
;
typedef struct rt_object *rt_object_t;

2.3、获取指定类型对象信

tatic struct rt_object_information rt_object_container[RT_Object_Info_Unknown] =
    
//   初始化容器对象 --线程(对象类型)
        
         RT_Object_Class_Thread,
         //  初始化对象列表节点头里面的 next 和 prev 两个节点指 针分别指向自身(对象列表节点)
         _OBJ_CONTAINER_LIST_INIT(RT_Object_info_Thread),
         //   获取线程对象的大小,即整个线程控制块的大小
         sizeof(struct rt_thread),

//  初始化对象容器--信号量
#ifdef RT_USING_SEMAPHORE
        RT_Object_Class_Semaphore,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Semaphore),
         sizeof(struct rt_semaphore),
#endif

//  初始化对象容器--互斥量
#ifdef RT_USING_MUTEX
        RT_Object_Class_Mutex,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Mutex),
         sizeof(struct rt_Mutex),
#endif

//  邮箱
#ifdef RT_USIGN_MAILBOX
        RT_Object_Class_mailBox,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_mailBox),
         sizeof(struct rt_mailBox) ,
#endif

//  事件  初始化对象容器—事件,由宏 RT_USING_EVENT 决定
#ifdef RT_USIGN_EVENT
        RT_Object_Class_Event,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Event),
         sizeof(struct rt_Event) ,
#endif
//  消息队列
#ifdef RT_USIGN_MESSAGEQUEUE
        RT_Object_Class_MessageQueue,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_MessageQueue),
         sizeof(struct rt_MessageQueue) ,
#endif
//  内存堆
#ifdef RT_USIGN_MEMHEAP
        RT_Object_Class_MemHeap,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_MemHeap),
         sizeof(struct rt_MemHeap) ,
#endif
//  内存池
#ifdef RT_USIGN_MEMPOOL
        RT_Object_Class_MemPool,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_MemPool),
         sizeof(struct rt_Mempool) ,
#endif

//  设备
#ifdef RT_USIGN_DEVICE
        RT_Object_Class_Device,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Device),
         sizeof(struct rt_Device) ,
#endif

//  定时器
#ifdef RT_USIGN_TIMER
        RT_Object_Class_Timer,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Timer),
         sizeof(struct rt_Timer) ,
#endif
//  模块
#ifdef RT_USIGN_MODULE
        RT_Object_Class_Module,
         _OBJ_CONTANER_LIST_INIT(RT_Object_Info_Module),
         sizeof(struct rt_Module) ,
#endif
;
/*获取指定类型的对象*/


/** 
* 该函数将初始化对象并将对象添加到对象容器中 
* 
* @param object 要初始化的对象 
* @param type 对象的类型 
* @param name 对象的名字,在整个系统中,对象的名字必须是唯一的 
*/
// const修饰的变量具有常属性,不可以修改它的值。  修饰形参时,保护形参不被修改
void rt_object_init(struct rt_object *object,enum rt_object_class_type type,const char *name)

	   //  register 定义局部变量  将变量存入寄存器,寄存器中的访问比内快
	   //  一般的只有编译器将变量优化后才能存入寄存器
    register rt_base_t temp;
	  struct rt_object_information *information;
	
	  //  获取对象信息,从容器中拿到对应对象列表头指针
	  information = rt_object_get_information(type);
	
	  //  设置对象类型为静态
	  object->type = type|RT_Object_Class_Static;
	
	 //  拷贝名字
	rt_strncpy(object->name,name,RT_NAME_MAX);
	
	//  关中断 接下来链表的操作不希望被中断
	temp = rt_hw_interrupt_disable();
	
	//  将对象插入到容器的对应列表中,不同类型的对象所在的列表不一样
	rt_list_insert_after(&(information->object_list),&(object->list));
	
	//  使能中断
	rt_hw_interrupt_enable(temp);




2.4、对象初始化

/** 
* 获取指定类型的对象信息 
*  
* @param type 对象类似 
* @return 对象信息 or RT_NULL 
*/

//  指针函数:返回值为指针的函数(地址值)   返回值是一个指向rt_object_information(地址类型)的指针
struct rt_object_information *rt_object_get_information(enum rt_object_class_type type)

    int index;
	  for(index=0;index<RT_Object_Info_Unknown;index++)
	  if(rt_object_container[index].type==type)return&rt_object_container[index];
    return RT_NULL;


2.5、调用初始化函数

#include "public.h"

// rt开头+文件名+函数名    表示外部函数,可以由用户调用。
//_rt开头+文件名+函数名   表示内部函数, 只可以在RT_thread内部使用。



/**************************************************************
线程函数
功能:关联线程栈,线程函数实体,线程控制块
所有跟线程相关的函数都在此文件中实现
**************************************************************/
//  1、线程结构体(控制块)指针  2、线程入口   3、线程参数 4、线程栈的起始地址  5、线程栈的大小,单位为字节
rt_err_t rt_thread_init(struct rt_thread *thread,
                        const char       *name,
                        void (*entry)(void *parameter),
                        void             *parameter,
                        void             *stack_start,
                        rt_uint32_t       stack_size)

	
	// 线程对象初始化
	rt_object_init((rt_object_t)thread,RT_Object_Class_Thread,name);
	//  初始化线程链表节点,通过它来实现把线程插入各种链表(类似于一个钩子,把线程控制块挂载在各种链表)
   rt_list_init(&(thread->tlist));
	
	//  将线程入口保存到线程控制块的 entry 成员中。
	 thread ->entry = (void*)entry;
	
	//  将线程入口形参保存到线程控制块的 parameter 成员中。
	 thread ->parameter = parameter;
	
	 // 将线程栈起始地址保存到线程控制块的 stack_start 成员中。
	 thread ->stack_addr = stack_start;
	 
	 //  将线程栈起大小保存到线程控制块的 stack_size 成员
	 thread  ->stack_size = stack_size;
	
	 //  初始化线程栈,并返回线程栈顶指针。rt_hw_stack_init()
	thread->sp = (void *)rt_hw_stack_init( thread->entry, 
		                                   thread->parameter,
							               (void *)((char *)thread->stack_addr + thread->stack_size - 4) );
	
	//  初始化线程成功返回错误码 RT_EOK
	return RT_EOK;
 

 

以上是关于对象容器的实现的主要内容,如果未能解决你的问题,请参考以下文章

对象容器的实现

一起写框架-Ioc内核容器的实现-对象的调用-@Bean注解注入容器的对象

一起写框架-Ioc内核容器的实现-基础功能-容器对象名默认首字母小写

深入springIoC容器的实现

手动向Spring容器中注入对象

C++ STL - 容器实现