NDAttributeList源码解析及测试

 NDAttributeList对象的源代码:

#include 

#include "NDAttributeList.h"

/** NDAttributeList构造器:初始化ELLLIST,创建互斥量
  */
NDAttributeList::NDAttributeList()
{
  ellInit(&this->list_);
  this->lock_ = epicsMutexCreate();
}

/** NDAttributeList析构函数:清除所有NDAttribute对象,释放ELLLIST,销毁互斥量
  */
NDAttributeList::~NDAttributeList()
{
  this->clear();
  ellFree(&this->list_);
  epicsMutexDestroy(this->lock_);
}

/** 添加一个属性到这个列表。
  * 如果一个相同名称的属性已经存在,则删除这个已有属性并且用这个新属性替代。
  * [in] pAttribute:指向要添加的属性的指针 .
  */
int NDAttributeList::add(NDAttribute *pAttribute)
{
  //const char *functionName = "NDAttributeList::add";

  epicsMutexLock(this->lock_);
  /* 移除这个名称的任何已有顺序 */
  this->remove(pAttribute->name_.c_str());
  // 把这个属性添加到链表中
  ellAdd(&this->list_, &pAttribute->listNode_.node);
  epicsMutexUnlock(this->lock_);
  return(ND_SUCCESS);
}

/** 添加一个NDAttribute对象到链表中
  * 这是一个用于添加一个属性到一个链表的便捷函数.
  * 它首先搜寻这个链表查看是否有存在一个相同名称的属性。
  * 如果存在,它仅更改已有属性的性质。如果不存在,它用指定性质创建一个新的属性。
  * 重要:这个方法仅能够创建NDAttribute基类类型的属性,而非派生类属性。
  * 要添加一个派生类的属性到一个列表,必须使用NDAttributeList::add(NDAttribute *)方法。
  * [in] pName :要被添加的属性的名称.
  * [in] pDescription:这个属性的描述.
  * [in] dataType :这个属性的数据类型.
  * [in] pValue :指向用于这个属性的值的指针.
  *
  */
NDAttribute* NDAttributeList::add(const char *pName, const char *pDescription, NDAttrDataType_t dataType, void *pValue)
{
  //const char *functionName = "NDAttributeList::add";
  NDAttribute *pAttribute;

  epicsMutexLock(this->lock_);
  pAttribute = this->find(pName);
  if (pAttribute) {
    pAttribute->setValue(pValue);
  } else {
    pAttribute = new NDAttribute(pName, pDescription, NDAttrSourceDriver, "Driver", dataType, pValue);
    ellAdd(&this->list_, &pAttribute->listNode_.node);
  }
  epicsMutexUnlock(this->lock_);
  return(pAttribute);
}



/**  通过名称查找一个属性;搜索现在是区分大小写的。
  * [in] pName : 要被查找的属性的名称.
  * 返回:如果找到,一个指向这个属性的指针,如果没有找到,返回NULL .
  */
NDAttribute* NDAttributeList::find(const char *pName)
{
  NDAttribute *pAttribute;
  NDAttributeListNode *pListNode;
  //const char *functionName = "NDAttributeList::find";

  epicsMutexLock(this->lock_);
  pListNode = (NDAttributeListNode *)ellFirst(&this->list_);
  while (pListNode) {
    pAttribute = pListNode->pNDAttribute;
    if (pAttribute->name_ == pName) goto done;
    pListNode = (NDAttributeListNode *)ellNext(&pListNode->node);
  }
  pAttribute = NULL;

  done:
  epicsMutexUnlock(this->lock_);
  return(pAttribute);
}

/** 查找在属性链表中下一个属性。
  * [in] pAttributeIn : 一个指向链表中前一个属性的指针
  * 如果NULL,返回链表中第一个属性
  * 返回:如果有,返回一个指向下一个属性的指针,
  * 如果在链表中没有更多属性了,返回NULL。
  */
NDAttribute* NDAttributeList::next(NDAttribute *pAttributeIn)
{
  NDAttribute *pAttribute=NULL;
  NDAttributeListNode *pListNode;
  //const char *functionName = "NDAttributeList::next";

  epicsMutexLock(this->lock_);
  if (!pAttributeIn) {
    pListNode = (NDAttributeListNode *)ellFirst(&this->list_);
   }
  else {
    pListNode = (NDAttributeListNode *)ellNext(&pAttributeIn->listNode_.node);
  }
  if (pListNode) pAttribute = pListNode->pNDAttribute;
  epicsMutexUnlock(this->lock_);
  return(pAttribute);
}

/** 返回属性链表中属性的总数。
  * 返回:返回属性数目  */
int NDAttributeList::count()
{
  //const char *functionName = "NDAttributeList::count";
  // 链表中节点数目
  return ellCount(&this->list_);
}

/** 从链表中移除一个属性。
  * [in] pName : 要被删除的属性名称.
  * 返回:如果找到这个属性并且被删除,返回ND_SUCCESS。
  * 如果没有找到这个属性,ND_ERRORR
  */
int NDAttributeList::remove(const char *pName)
{
  NDAttribute *pAttribute;
  int status = ND_ERROR;
  //const char *functionName = "NDAttributeList::remove";

  epicsMutexLock(this->lock_);
  pAttribute = this->find(pName);
  if (!pAttribute) goto done; // 指定名称的属性不存在,则直接结束
  ellDelete(&this->list_, &pAttribute->listNode_.node); // 从链表中删除这个属性
  delete pAttribute;
  status = ND_SUCCESS;

  done:
  epicsMutexUnlock(this->lock_);
  return(status);
}

/**  从链表删除所有属性 */
int NDAttributeList::clear()
{
  NDAttribute *pAttribute;
  NDAttributeListNode *pListNode;
  //const char *functionName = "NDAttributeList::clear";

  epicsMutexLock(this->lock_);
  pListNode = (NDAttributeListNode *)ellFirst(&this->list_); // 第一个节点
  while (pListNode) {
    pAttribute = pListNode->pNDAttribute;
    ellDelete(&this->list_, &pListNode->node);
    delete pAttribute;
    pListNode = (NDAttributeListNode *)ellFirst(&this->list_);
  }
  epicsMutexUnlock(this->lock_);
  return(ND_SUCCESS);
}

/** 
  * 从一个属性链表复制所有属性到另一个属性链表。
  * 它是高效的,因而如果这个属性已经存在于这个输出链表,它仅复制这些性质,并且内存分配被最小化。
  * 这些属性被添加到在输出链表中已经存在的任何已有属性中。
  * [out]pListNode: 指向要复制到的输出属性链表的指针
  */
int NDAttributeList::copy(NDAttributeList *pListOut)
{
  NDAttribute *pAttrIn, *pAttrOut, *pFound;
  NDAttributeListNode *pListNode;
  //const char *functionName = "NDAttributeList::copy";

  epicsMutexLock(this->lock_);
  pListNode = (NDAttributeListNode *)ellFirst(&this->list_); // 获取第一个属性所在节点
  while (pListNode) {
    pAttrIn = pListNode->pNDAttribute; // 获取属性NDAttribute对象
    /* 查找输出链表中是否已经存在相同名称的属性  */
    pFound = pListOut->find(pAttrIn->name_.c_str());
    /* 如果输出链表中存在相同名称的,则将仅将输入链表中属性对象的属性值复制到输出链表中属性对象的属性值中
       如果不存在,则拷贝构造一个输入链表中的属性对象
    */
    pAttrOut = pAttrIn->copy(pFound);
    /* 如果pFound是NULL,则一个复制窗一个新属性,需要添加它到输出链表*/
    if (!pFound) pListOut->add(pAttrOut); 
    pListNode = (NDAttributeListNode *)ellNext(&pListNode->node);// 输入链表中当前节点的下一个节点
  }
  epicsMutexUnlock(this->lock_);
  return(ND_SUCCESS);
}

/** 
  * 更新链表中所有属性值;为链表中每个属性调用NDAttribute::updateValue()
  */
int NDAttributeList::updateValues()
{
  NDAttribute *pAttribute;
  NDAttributeListNode *pListNode;
  //const char *functionName = "NDAttributeList::updateValues";

  epicsMutexLock(this->lock_);
  pListNode = (NDAttributeListNode *)ellFirst(&this->list_);
  while (pListNode) {// 调用链表中每个节点上每个NDAttribute对象的updateValue()
    pAttribute = pListNode->pNDAttribute;
    pAttribute->updateValue();
    pListNode = (NDAttributeListNode *)ellNext(&pListNode->node);
  }
  epicsMutexUnlock(this->lock_);
  return(ND_SUCCESS);
}

/** 报告这个属性链表的性质。
  * [in] fp :报告输出的文件指针
  * [in] details : 所需报告的详细程度;如果>10, 为每个属性调用NDAttribute::report()。
  */
int NDAttributeList::report(FILE *fp, int details)
{
  NDAttribute *pAttribute;
  NDAttributeListNode *pListNode;

  epicsMutexLock(this->lock_);
  fprintf(fp, "\n");
  fprintf(fp, "NDAttributeList: address=%p:\n", this);
  fprintf(fp, "  number of attributes=%d\n", this->count());
  if (details > 10) {
    pListNode = (NDAttributeListNode *) ellFirst(&this->list_);
    while (pListNode) {
      pAttribute = (NDAttribute *)pListNode->pNDAttribute;
      pAttribute->report(fp, details);
      pListNode = (NDAttributeListNode *) ellNext(&pListNode->node);
    }
  }
  epicsMutexUnlock(this->lock_);
  return ND_SUCCESS;
}

测试代码:

#include 
#include 
#include 
#include "NDAttribute.h"
#include "NDAttributeList.h"

int main()
{
        NDAttributeList * list = new NDAttributeList();
        epicsInt8 i8 = 10;
        epicsInt16 i16 = 256;
        epicsInt32 i32 = 100000;
        epicsFloat64 f64 = 3.14;
        const char * str = "Hello World";

        NDAttrDataType_t types[] = {NDAttrInt8, NDAttrInt16, NDAttrInt32, NDAttrFloat64, NDAttrString};
        void * ptrValue[] = {&i8, &i16, &i32, &f64, (void *)str};
        const char * pDescription[] = {"NDInt8", "NDInt16", "NDInt32", "NDFloat64", "NDString"};
        const char * name[] = {"i8Attribute", "i16Attribute", "i32Attribute", "f64Attribute", "strAttribute"};

        int i;

        for (i = 0; i < 5; i++){
                list->add(name[i], pDescription[i], types[i], ptrValue[i]);
        }

        printf("Total number of Attributes: %d\n", list->count());
        printf("Find the attribute of name: %s\n", name[4]);
        NDAttribute * pAttribute = list->find(name[4]);

        if (pAttribute){
                printf("find the attribute of name %s\n", name[4]);
                pAttribute->report(stdout, 10);
        }
        else
        {
                printf("can not find the attribute of the name: %s\n", name[4]);
        }

        printf("Display all attribute: \n");
        pAttribute = list->next(NULL);

        printf("\n");

        i = 0;
        while (pAttribute){
                printf("Num:%d", ++i);
                pAttribute->report(stdout, 10);
                pAttribute = list->next(pAttribute);
        }

        printf("Delete the attribute of the name: %s\n", name[4]);
        list->remove(name[4]);
        printf("Total number of Attributes: %d\n", list->count());
        if (pAttribute){
                printf("find the attribute of name %s\n", name[4]);
                pAttribute->report(stdout, 10);
        }
        else
        {
                printf("can not find the attribute of the name: %s\n", name[4]);
        }


        return 0;
}

编译以上源代码,进行测试,解释结果如下:

Total number of Attributes: 5
Find the attribute of name: strAttribute
find the attribute of name strAttribute

NDAttribute, address=0xaaaac52ab020:
  name=strAttribute
  description=NDString
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrString
  value=Hello World
Display all attribute:

Num:1
NDAttribute, address=0xaaaac52aabe0:
  name=i8Attribute
  description=NDInt8
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrInt8
  value=10
Num:2
NDAttribute, address=0xaaaac52aacf0:
  name=i16Attribute
  description=NDInt16
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrInt16
  value=256
Num:3
NDAttribute, address=0xaaaac52aae00:
  name=i32Attribute
  description=NDInt32
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrInt32
  value=100000
Num:4
NDAttribute, address=0xaaaac52aaf10:
  name=f64Attribute
  description=NDFloat64
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrFloat64
  value=3.140000
Num:5
NDAttribute, address=0xaaaac52ab020:
  name=strAttribute
  description=NDString
  source type=0
  source type string=NDAttrSourceDriver
  source=Driver
  dataType=NDAttrString
  value=Hello World
Delete the attribute of the name: strAttribute
Total number of Attributes: 4
can not find the attribute of the name: strAttribute

你可能感兴趣的:(EPICS教程,Linux,C,EPICS,C语言)