【发布时间】:2017-01-11 14:10:07
【问题描述】:
Below(image) 是来自Linux/net/socket.c 源的模仿方法。
背景:
用这种方法实现
List抽象的原因是在实现snmp库之前用同样的方法制作一个工作原型。 F 灵感来自Linux/net/socket.c,其中任何一个协议族实现(如net/ipv4/af_inet.c或net/unix/af_unix.c/..)在调用socket()接口 api 时可用客户端调用
socket()api,基于传递给socket()接口api 的参数(AF_INET|AF_UNIX|AF_XYZ) 使用任何一个 协议族实现。
上述方法中,list.h提供List接口,代码如下,
/********************** list.h ********************/
#ifndef LIST_H /* Header guard */
#define LIST_H
#include"type.h"
/****************** Interface - start ********/
typedef struct List List;
typedef enum {ARRAY_IMPL, LINKED_LIST_IMPL}ImplType;
typedef int (*compareTo)(const void *, const void *);
typedef bool (*isLess)(const void *, const void *);
typedef bool (*isEqual)(const void *, const void *);
List* createList(ImplType);
void freeList(List*);
void swim(List*, int, isLess);
void sink(List*, int, isLess);
const void* deleteMax(List*, isLess);
const void* sortDeleteMax(List*);
int getSize(List*);
const void* getItem(List*, const int);
List* sortInsertItem(List*, const void*, compareTo);
void insertItem(List*, const void*);
const void* deleteItem(List*, int);
const void* deleteLastItem(List*);
const void* deleteFirstItem(List*);
int lSearch(const void*, List*, size_t, compareTo);
int bSearch(const void*, List*, size_t, compareTo);
void callInsertionSort(List*, size_t, isLess);
void callMergeSort(List*, size_t, isLess);
void swap(List*, int, int);
/****************** Interface - end ********/
#endif
实现(arrayImpl.o/linkListImpl.o)到可执行文件(a.out)的链接发生在链接器阶段。
virtualImplLayer.c 根据传递给createList() 接口api 的参数(ARRAY_IMPL | LINKED_LIST_IMPL) 选择任何一个 实现处理程序。此实现处理程序存储在handler 全局变量中,如下所示。 接口 api 的其余部分依赖于这个全局变量。
/*****************virtualImplLayer.c*************************/
#include "list/listHandler.h"
/*****Private symbol - start *****************/
static ListHandler * findListImplHandler(ImplType);
/*****Private symbol - end *****************/
ListHandler *handler = NULL;
/***** User interface - start *************/
List* createList(ImplType implType){
handler = findListImplHandler(implType);
if(handler != NULL){
List *list = handler->createList();
return list;
}
fprintf(stderr, "createList() - No implementation for this feature\n");
return NULL;
}
void freeList(List *list){
handler->freeList(list);
}
void swim(List *list, int parentIndex, isLess less){
handler->swim(list, parentIndex, less);
}
void sink(List *list, int index, isLess less){
handler->sink(list, index, less);
}
const void* deleteMax(List *list, isLess less){
return handler->listDeleteMaxElement(list, less);
}
const void* sortDeleteMax(List *list){
return handler->sortedListDeleteMaxElement(list);
}
int getSize(List *list){
return handler->listGetSize(list);
}
const void* getItem(List *list, const int index){
return handler->listGetItem(list, index);
}
List* sortInsertItem(List *list, const void *item, compareTo compare){
return handler->sortedListInsertItem(list, item, compare);
}
void insertItem(List *list, const void *item){
handler->listInsertItem(list, item);
}
const void* deleteItem(List *list, int listIndex){
return handler->listDeleteItem(list, listIndex);
}
const void* deleteLastItem(List *list){
return handler->listDeleteLastItem(list);
}
const void* deleteFirstItem(List *list){
return handler->listDeleteFirstItem(list);
}
int lSearch(const void *key, List *list, size_t size, compareTo compare){
return handler->linearSearch(key, list, size, compare);
}
int bSearch(const void *key, List *list, size_t size, compareTo compare){
return handler->binarySearch(key, list, size, compare);
}
void callInsertionSort(List *list, size_t size, isLess less){
handler->insertionSort(list, size, less);
}
void callMergeSort(List *list, size_t size, isLess less){
handler->mergeSort(list, size, less);
}
void swap(List *list, int i, int j){
handler->swap(list, i, j);
}
/***** User interface -end *************/
/*****Private symbol - start *****************/
static ListHandler * findListImplHandler(ImplType implType){
ListHandler *implHandler = NULL;
int handlerIndex = 0;
while(listHandlers[handlerIndex] !=NULL){
implHandler = listHandlers[handlerIndex];
if( implHandler->canHandle(implType) ){
return implHandler;
}
handlerIndex++;
}
return NULL;
}
/*****Private symbol - end *****************/
Linux/net/ipv4/af_inet.c,Linux/net/unix/af_unix.c 等实现在加载阶段通过覆盖实现中的_init() 运行时代码(比如af_inet.c)链接,如下所示,
static int __init inet_init(void){
....
void)sock_register(&inet_family_ops);
....
}
谈到问题,在virtualImplLayer.c 中给定实现,客户端程序不能期望使用/访问多个 实现(arrayImpl.c/LinkListImpl.c),因为handler变量被覆盖
问题:
ImplType 仅传递给createList() 接口,在virtualImplLayer.c 中,如何避免覆盖全局变量handler,以利用多个实现?
【问题讨论】:
-
完全没有全局变量 (virtualImplLayer.c)。让
findListImplHandler缓存结果以便于查找。在使用任何 1 个列表实现时,查找速度会很快。切换时会导致一次查找未命中。 -
现在是一个挑剔的人,因为我认为你的问题很好。但是您确实需要处理minimal reproducible example 的“最小”方面。
-
@StoryTeller 更新了查询,包含工作示例的详细信息
-
你的例子并不缺乏细节。恰恰相反。如果有人想真正理解你的问题,他们需要筛选很多不相关的细节(是的,你展示的大部分代码以及设计说明都是无关紧要的)。
-
@StoryTeller 好的。如果有不相关的详细信息,请编辑查询
标签: c coding-style refactoring