diff --git a/Net.xcodeproj/project.pbxproj b/Net.xcodeproj/project.pbxproj index 257ee0e..4f35040 100644 --- a/Net.xcodeproj/project.pbxproj +++ b/Net.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 9221DA1121EB5FB8007310A7 /* net.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9221DA1021EB5FB8007310A7 /* net.cpp */; }; 925A13A621EC68D500CBD427 /* cpart.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 925A13A421EC67C900CBD427 /* cpart.cpp */; }; + 925A13A921EC973000CBD427 /* cmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 925A13A721EC973000CBD427 /* cmap.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -30,6 +31,8 @@ 9221DA1421EB62F6007310A7 /* cpart.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cpart.h; sourceTree = ""; }; 9221DA1621EB8C02007310A7 /* pcs.map */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.module-map"; name = pcs.map; path = build/Debug/PCS/pcs.map; sourceTree = ""; }; 925A13A421EC67C900CBD427 /* cpart.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cpart.cpp; sourceTree = ""; }; + 925A13A721EC973000CBD427 /* cmap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = cmap.cpp; sourceTree = ""; }; + 925A13A821EC973000CBD427 /* cmap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cmap.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,15 +65,25 @@ 9221DA0E21EB5FAD007310A7 /* Net */ = { isa = PBXGroup; children = ( + 925A13AA21EC989500CBD427 /* include */, 9221DA1021EB5FB8007310A7 /* net.cpp */, - 9221DA0F21EB5FB8007310A7 /* net.h */, - 9221DA1421EB62F6007310A7 /* cpart.h */, 9221DA1621EB8C02007310A7 /* pcs.map */, 925A13A421EC67C900CBD427 /* cpart.cpp */, + 925A13A721EC973000CBD427 /* cmap.cpp */, ); name = Net; sourceTree = ""; }; + 925A13AA21EC989500CBD427 /* include */ = { + isa = PBXGroup; + children = ( + 9221DA0F21EB5FB8007310A7 /* net.h */, + 9221DA1421EB62F6007310A7 /* cpart.h */, + 925A13A821EC973000CBD427 /* cmap.h */, + ); + name = include; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -129,6 +142,7 @@ files = ( 9221DA1121EB5FB8007310A7 /* net.cpp in Sources */, 925A13A621EC68D500CBD427 /* cpart.cpp in Sources */, + 925A13A921EC973000CBD427 /* cmap.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/cmap.cpp b/cmap.cpp new file mode 100644 index 0000000..978d77d --- /dev/null +++ b/cmap.cpp @@ -0,0 +1,160 @@ +// +// cmap.cpp +// Net +// +// Created by 胡一兵 on 2019/1/14. +// Copyright © 2019年 Bakantu. All rights reserved. +// + +#include "cmap.h" + + +CMap::CMap(string path){ + ifstream map; + map.open(path+"/pcs.map"); + this->path = path; +// 如果文件存在且打开成功 + if(map.good()){ + string line; + map>>line; +// 读取计算模块信息 + if(line == "#PCS"){ + BuildCPart(map); + } + map>>line; +// 读取计算模块之间的依赖关系信息 + if(line == "#DEPEND"){ + BuildConnection(map); + } + + } + else throw "fail to open pcs.map"; +} + +void CMap::BuildCPart(ifstream &map){ + string line; + map>>line; +// 从初始行开始读取在描述结束符之前的所有行 + while(line!="END"){ +// 定位括号,来截取计算模块的名字 + unsigned long qs = line.find('(',0), qe = line.find(')',0); + string name = line.substr(qs+1,qe-qs-1); +// 定位尖括号来截取计算模块所在源文件的名字 + qs = line.find('<',0); + qe = line.find('>',0); + string src_name = line.substr(qs+1,qe-qs-1); + +// 根据以上信息构造计算管理结构对象 + CPart *ncp = new CPart(path,src_name,name); +// 在列表中加入该对象 + this->cparts.insert(pair(name,ncp)); + +// 构造该计算模块的输入与输出形式参数列表 + vectorfargs_in,fargs_out; + map>>line; + if(line[0] == '>'){ + fargs_in = BuidArgs(line); + } + map>>line; + if(line[0] == '<'){ + fargs_out = BuidArgs(line); + } +// 设置输入与输出形式参数列表 + ncp->setArgsType(fargs_in, fargs_out); +// 读入下一行 + map>>line; + } +} + +vector CMap::BuidArgs(string &line){ + vector fargs; + unsigned long qs,qe; +// 定位方括号来获得函数的作用域 + qs = line.find('[',0); + qe = line.find(']',0); + unsigned long idx = qs; + while(idx < qe){ + unsigned long ts,te; +// 截取冒号与逗号之间的类型信息 + ts = line.find(':',idx); + te = line.find(',',ts); + if(te == string::npos){ + te = qe; + } + string type = line.substr(ts+1,te-ts-1); +// 在形式参数列表中加入类型信息 + if(type == "int") + fargs.push_back(INT); + else if(type == "double") + fargs.push_back(DOUBLE); + +// 向下移动 + idx = te; + } + return fargs; +} + + +void CMap::BuildConnection(ifstream &map){ + string line; + map>>line; +// 从初始行开始读取在描述结束符之前的所有行 + while(line != "END"){ +// 定位圆括号来截取计算模块的名字 + unsigned long qs = line.find('(',0), qe = line.find(')',0); + string name = line.substr(qs+1,qe-qs-1); +// 通过计算模块的名字在参数列表中找到对应的计算模块 + CPart *p_ncp = cparts.find(name)->second; +// 定位大括号来截取依赖模块的列表 + unsigned long idx = line.find('{',qe); + unsigned long ss = line.find('}',idx); + unsigned long ts, te; + while(idx+1 < ss){ +// 定位圆括号与方括号来截取依赖的计算模块的名字及依赖的相关参数信息 + ts = line.find('(',idx); + te = line.find(']',ts); + if(te == string::npos){ + te = ss; + } +// 在计算模块管理结构中添加构造的依赖信息管理结构 + string item = line.substr(ts,te-ts+1); + p_ncp->depends.push_back(ReadItem(item)); + //cout<>line; + } +} + +Depends CMap::ReadItem(string item){ +// 构造依赖关系信息结构 + Depends dep; +// 定位圆括号来截取计算模块的名字 + unsigned long qs = item.find('(',0), qe = item.find(')',qs); + string name = item.substr(qs+1,qe-qs-1); +// 通过模块名字在模块列表中找到相应模块 + dep.t_cpart = cparts.find(name)->second; +// 定位方括号来截取依赖参数信息 + unsigned long idx = item.find('[',0),ss = item.find(']',idx); + unsigned long ts, te; + while(idx < ss){ + ts = idx; + te = item.find(',',ts+1); + if(te == string::npos){ + te = ss; + } +// 将字符串转换为整数 + string arg = item.substr(ts+1,te-ts-1); + std::stringstream sstr; + int darg; + sstr<>darg; +// 加入依赖参数序号信息 + dep.args.push_back(darg); +// 向下移动 + idx = te; + } + return dep; +} diff --git a/cmap.h b/cmap.h new file mode 100644 index 0000000..0c46262 --- /dev/null +++ b/cmap.h @@ -0,0 +1,41 @@ +// +// cmap.hpp +// Net +// +// Created by 胡一兵 on 2019/1/14. +// Copyright © 2019年 Bakantu. All rights reserved. +// + +#ifndef cmap_h +#define cmap_h + +#include "cpart.h" +#include +#include +#include + +using std::map; +using std::ifstream; +using std::pair; + +//计算任务无环有向图管理 +class CMap{ +public: +// 图中包含的的计算模块列表 + map cparts; +// 图目录所在的目录 + string path; +// 构造函数传入图包所在的目录 + CMap(string path); +// 根据图的表述文件构造计算模块列表 + void BuildCPart(ifstream &map); +// 根据图表述文件中的描述信息,处理并转化为形式输入或输出参数列表 + vector BuidArgs(string &line); +// 根据图的表述文件构造计算模块之间的依赖关系 + void BuildConnection(ifstream &map); +// 根据图描述文件依赖关系描述语句所提供的信息转化为依赖关系结构 + Depends ReadItem(string item); + +}; + +#endif /* cmap_h */ diff --git a/cpart.cpp b/cpart.cpp index 2a2e689..a52ee35 100644 --- a/cpart.cpp +++ b/cpart.cpp @@ -8,47 +8,103 @@ #include "cpart.h" -CPart::CPart(string src_path,string src_name,string name){ +/** + 设置计算模块的接口形式 + + @param src_path 源文件所在的目录地址 + @param src_name 源文件的名字 + @param name 计算模块的名字 + @param ffresh 每次建立该结构都重新编译一次源文件 + */ +CPart::CPart(string src_path,string src_name,string name,bool ffresh = true){ this->src_path = src_path; this->name = name; +// 去掉源文件的后缀 unsigned long qp = src_name.find(".",0); - string t_libname = "lib"+src_name.substr(0,qp)+".so"; - if(!~access(("Libs/"+t_libname).data(), F_OK)){ - system(("g++ -fPIC -shared -std=c++11 -o ./Libs/"+t_libname+" "+src_path+"/"+src_name).data()); + if(qp == string::npos){ + qp = src_name.size()-1; } +// 生成lib文件的文件名 + string t_libname = "lib"+src_name.substr(0,qp)+".so"; +// 如果lib文件存在且不要求每次建立该结构都重新编译一次源文件的话就不执行编译 + if(!~access(("Libs/"+t_libname).data(), F_OK) || ffresh) + BuildSo(); +// 记录必要信息 this->libname = t_libname; - this->handle = dlopen(("Libs/"+t_libname).data(), RTLD_NOW | RTLD_GLOBAL); - this->func = (PCSFUNC) dlsym(this->handle, this->name.data()); - this->libargs_in = (vector *) dlsym(this->handle, ("__"+name+"_args_in").data()); - this->libargs_out = (vector *) dlsym(this->handle, ("__"+name+"_args_out").data()); + this->src_name = src_name; + } -CPart::CPart(string name){ - this->name = name; - this->libname = "lib"+name+".so"; - this->handle = dlopen(this->libname.data(), RTLD_LAZY | RTLD_GLOBAL); + +/** + 执行源文件编译操作,生成动态链接库 + + @return 执行成功将返回0 + */ +int CPart::BuildSo(void){ + int rtn = system(("g++ -fPIC -shared -std=c++11 -o ./Libs/"+libname+" "+src_path+"/"+src_name).data()); + if(rtn != -1 && rtn != 127) + return 0; + else throw "fail to build lib file"; +} + + +/** + 获得lib文件的操作柄,并获得计算模块的入口地址及传入传出参数列表的地址。 + + @return 执行成功则返回0 + */ +int CPart::GetSo(void){ + // 读取lib文件 + this->handle = dlopen(("Libs/"+libname).data(), RTLD_NOW | RTLD_GLOBAL); + if(this->handle == nullptr) throw "can not open lib file"; + // 获得该模块的入口 this->func = (PCSFUNC) dlsym(this->handle, this->name.data()); + if(this->func == nullptr) throw "can not get func "+this->name; + // 获得向该模块传入参数的vector的地址 + this->libargs_in = (vector *) dlsym(this->handle, ("__"+name+"_args_in").data()); + if(this->libargs_in == nullptr) throw "can not get the address of __"+name+"_args_in"; + // 获得该函数传出参数所在的vector的地址 + this->libargs_out = (vector *) dlsym(this->handle, ("__"+name+"_args_out").data()); + if(this->libargs_out == nullptr) throw "can not get the address of __"+name+"_args_out"; + return 0; } CPart::~CPart(){ +// 释放储存接口输入参数所占用的内存 for(auto k = 0; k < args_in.size(); k++){ if(fargs_in[k] == 0) delete (int *)(args_in[k]); else delete (double *)(args_in[k]); } +// 释放储存接口输出参数所占用的内存 for(auto k = 0; k < args_out.size(); k++){ if(fargs_in[k] == 0) delete (int *)(args_out[k]); else delete (double *)(args_out[k]); } +// 停止对lib文件的操作 if(handle != nullptr) dlclose(handle); } + +/** + 设置计算模块的接口形式 + + @param fargs_in 调用接口形式 + @param fargs_out 输出接口形式 + */ void CPart::setArgsType(vector fargs_in, vector fargs_out){ this->fargs_in = fargs_in; this->fargs_out = fargs_out; } +/** + 向计算模块传入参数,并运行计算模块,而后获得计算结果 + + @return 如果执行成功则返回SUCCESS + */ int CPart::Run(void){ +// 对计算模块传入参数 unsigned long count = fargs_in.size()-1; for(auto k = args_in.rbegin(); k != args_in.rend();k++,count--){ if(fargs_in[count] == INT){ @@ -58,8 +114,10 @@ int CPart::Run(void){ CPart::addArg(libargs_in, *((double *)(*k))); } } +// 执行计算模块 if(func() == SUCCESS){ int count = 0; +//储存计算结果 for(auto k = libargs_out->begin(); k != libargs_out->end();k++,count++){ if(fargs_out[count] == INT){ CPart::addArg(&args_out, *((int *)(*k))); @@ -73,13 +131,21 @@ int CPart::Run(void){ else return -1; } + +/** + 清空上一次的计算参数及结果数据,并释放相关内存空间 + */ void CPart::Clear(void){ - for(auto k = 0; k < args_in.size(); k++){ +// 释放传入参数所占的空间 + for(auto k = args_in.size() - 1; ~k; k--){ if(fargs_in[k] == INT) delete (int *)(args_in[k]); else delete (double *)(args_in[k]); + args_in.pop_back(); } - for(auto k = 0; k < args_out.size(); k++){ +// 释放传出参数所占用的内存空间 + for(auto k = args_out.size() - 1; ~k; k--){ if(fargs_in[k] == INT) delete (int *)(args_out[k]); else delete (double *)(args_out[k]); + args_out.pop_back(); } } diff --git a/cpart.h b/cpart.h index 1e754a6..ef936d8 100644 --- a/cpart.h +++ b/cpart.h @@ -17,64 +17,104 @@ using std::vector; using std::string; +//声明计算模块的传入与传出参数列表 #define ARGS_DECLAER(name) vector __##name##_args_in, __##name##_args_out +//声明计算模块的入口 #define PCSFUNC_DEFINE(name) extern "C" int name(void) #define GET_ARGS(name,type) CPart::popArg(&__##name##_args_in) #define ADD_ARGS(name,type,value) CPart::addArg(&__##name##_args_out, value); + +//从传入参数列表的第一个值,并删除该值 #define POP_ARGS(name,type) GET_ARGS( name ,type) +//向传出参数列表中添加值 #define PUSH_ARGS(name,type,value) ADD_ARGS( name ,type,value) #define INT 0 #define DOUBLE 1 + +//调用计算模块成功的返回 #define SUCCESS 0 -#define FAIL 1 +//调用计算模块失败的返回 +#define FAIL -1 typedef int(*PCSFUNC)(void); class CPart; +//计算模块管理对象间的依赖关系 class Depends{ public: +// 指向依赖的计算模块管理对象的指针 CPart *t_cpart; +// 所依赖的输入参数在计算模块输入参数列表中的序号 vector args; }; +//计算模块管理对象 class CPart{ public: +// 参数形式信息列表 vector fargs_in, fargs_out; +// 参数操纵列表 vector args_in, args_out; +// lib文件中相关参数操纵列表的地址 vector *libargs_in,*libargs_out; +// 所依赖的计算对象列表 vector depends; +// lib文件中的计算模块的入口地址 int (*func)(void); +// lib文件操作柄 void *handle; - string src_path,name,libname; +// 源文件所在目录 + string src_path; +// 计算模块名 + string name; +// lib文件名 + string libname; +// 源文件名 + string src_name; + +// 当计算模块随着该工具同时编译时可以直接使用该构造函数 CPart(PCSFUNC func):func(func),handle(nullptr){} - CPart(string src_path,string src_name,string name); - CPart(string name); +// 一般构造函数,计算模块在文件中以源文件的形式独立存在时使用该构造函数 + CPart(string src_path,string src_name,string name,bool ffresh = true); +// 析构函数 ~CPart(); +// 设置输入输出参数形式信息 void setArgsType(vector fargs_in, vector fargs_out); +// 编译源文件 + int BuildSo(void); +// 获得lib文件操作柄 + int GetSo(void); +// 运行计算模块 int Run(void); +// 清空计算历史记录 void Clear(void); +// 在对象的传入参数列表中添加参数值 template void addArgsIn(T value){ T *p_value = new T(value); + if(p_value == nullptr) throw "fail to malloc"; args_in.push_back(p_value); } - +// 一般由lib文件中的计算模块调用的向vector中添加参数并分配内存空间而后初始化 template static void addArg(vector *args,T value){ T *p_value = new T(value); + if(p_value == nullptr) throw "fail to malloc"; *p_value = value; args->push_back(p_value); } - +// 一般由lib文件中的计算模块调用的从vector中获得参数并释放其占用的内存空间而后返回相关值 template static T popArg(vector *args){ + if(args == nullptr) throw "the pointer to vector is null"; T *p_value = (T *)args->back(); + T value = *p_value; args->pop_back(); - return *p_value; + return value; } }; diff --git a/net.h b/net.h index 586ffda..2889939 100644 --- a/net.h +++ b/net.h @@ -178,130 +178,7 @@ public: } }; -class CMap{ -public: - map cparts; - string path; - CMap(string path){ - ifstream map; - map.open(path+"/pcs.map"); - this->path = path; - if(map.good()){ - string line; - map>>line; - if(line == "#PCS"){ - BuildCPart(map); - } - map>>line; - if(line == "#DEPEND"){ - BuildConnection(map); - } - - } - } - void BuildCPart(ifstream &map){ - string line; - map>>line; - while(line!="END"){ - unsigned long qs = line.find('(',0), qe = line.find(')',0); - string name = line.substr(qs+1,qe-qs-1); - qs = line.find('<',0); - qe = line.find('>',0); - string src_name = line.substr(qs+1,qe-qs-1); - - //std::cout<cparts.insert(pair(name,ncp)); - - vectorfargs_in,fargs_out; - map>>line; - if(line[0] == '>'){ - fargs_in = BuidArgs(line); - } - map>>line; - if(line[0] == '<'){ - fargs_out = BuidArgs(line); - } - ncp->setArgsType(fargs_in, fargs_out); - map>>line; - } - } - - vector BuidArgs(string &line){ - vector fargs; - unsigned long qs,qe; - qs = line.find('[',0); - qe = line.find(']',0); - unsigned long idx = qs; - while(idx < qe){ - unsigned long ts,te; - ts = line.find(':',idx); - te = line.find(',',ts); - if(te == string::npos){ - te = qe; - } - string type = line.substr(ts+1,te-ts-1); - if(type == "int") - fargs.push_back(INT); - else if(type == "double") - fargs.push_back(DOUBLE); - - idx = te; - } - return fargs; - } - - void BuildConnection(ifstream &map){ - string line; - map>>line; - while(line != "END"){ - unsigned long qs = line.find('(',0), qe = line.find(')',0); - string name = line.substr(qs+1,qe-qs-1); - CPart *p_ncp = cparts.find(name)->second; - unsigned long idx = line.find('{',qe); - unsigned long ss = line.find('}',idx); - unsigned long ts, te; - while(idx+1 < ss){ - ts = line.find('(',idx); - te = line.find(']',ts); - if(te == string::npos){ - te = ss; - } - string item = line.substr(ts,te-ts+1); - //cout<depends.push_back(ReadItem(item)); - } - map>>line; - } - - } - - Depends ReadItem(string item){ - Depends dep; - unsigned long qs = item.find('(',0), qe = item.find(')',qs); - string name = item.substr(qs+1,qe-qs-1); - dep.t_cpart = cparts.find(name)->second; - unsigned long idx = item.find('[',0),ss = item.find(']',idx); - unsigned long ts, te; - while(idx < ss){ - ts = idx; - te = item.find(',',ts+1); - if(te == string::npos){ - te = ss; - } - string arg = item.substr(ts+1,te-ts-1); - std::stringstream sstr; - int darg; - sstr<>darg; - dep.args.push_back(darg); - idx = te; - } - return dep; - } - -}; + class CThread{ public: