/*! * taskProject 类的实现。 * @author goldenhawking@163.com, 2016-09 */ #include "taskproject.h" #include "tasknode.h" #include "taskcell.h" #include "tb_interface.h" #include #include #include #include #include #include #include #include "process_prctl.h" #include "../watchdog/profile_log.h" QSet taskProject::m_instance_set; taskProject::taskProject(QObject * parent ): QObject(parent), m_fNewCell(std::bind(&taskProject::default_NewCell,this)), m_fInsAppended(std::bind(&taskProject::default_InsAppended,this,std::placeholders::_1,std::placeholders::_2,std::placeholders::_3)), m_fIndexRefreshed(std::bind(&taskProject::default_Indexrefreshed,this)), m_fGetCellPos(std::bind(&taskProject::default_GetCellPos,this,std::placeholders::_1)) { //初始化线程池。 for(int i=0;istart(); m_map_threadpool[pt].size(); } m_nTimerID = startTimer(200); } taskProject::~taskProject() { stop_project(); QList lstThreads = m_map_threadpool.keys(); foreach (QThread * k, lstThreads) { k->terminate(); k->wait(); } foreach (QThread * k, lstThreads) k->deleteLater(); foreach (taskNode * n, m_vec_nodes) n->deleteLater(); foreach (taskCell * n, m_vec_cells) { //由于在图形界面里,cell可能会派生出QObject的多重继承。因此,这里要判断。 //Because in the graphical interface, the cell may derive qobject //multiple inheritance. So, here to judge. QObject * obj = dynamic_cast (n); if (!obj) delete n; else if (obj->parent()==nullptr) obj->deleteLater(); } } quint32 taskProject::new_instance() { quint32 nextIns = 1; while (m_instance_set.contains(nextIns)) ++nextIns; m_instance_set.insert(nextIns); return nextIns; } void taskProject::unreg_instance(const quint32 ins) { m_instance_set.remove(ins); } /*! * \brief taskProject::append_instance 向本工程添加一个功能 * Add a component to the project. * \param json 功能描述 Function description * \param pt 构件初始的图形显示位置 The initial graphics position of the component * \param rebuildidxs 是否重建索引 Whether to rebuild the index */ void taskProject::add_node(const QString json,QPointF pt,bool rebuildidx) { taskNode * node = new taskNode(0); taskCell * mod = m_fNewCell(); mod->initFromJson(QByteArray(json.toStdString().c_str())); if (!mod->function_names().size()) node->deleteLater(); else { node->bindCell(mod); QString vname = mod->function_names().first(); mod->set_function_instance(vname,new_instance()); QMap mp_nice = mod->additional_paras(vname); //进程优先级默认值为“TASKBUS::pnice_norm”,一般优先级 //Process priority default value is "Taskbus::p nice_norm", //general priority if (mp_nice.contains("nice")==false) mp_nice["nice"] = TASKBUS::pnice_norm; mod->set_additional_paras(vname,mp_nice); m_vec_nodes.push_back(node); m_vec_cells.push_back(mod); //从线程池捡一个最空闲的线程承载新的节点通信。 //Pick one of the most idle threads from the thread pool to host //the new node communication QThread * bestTh = 0; int minLoad = 0x7fffffff; QList lstThreads = m_map_threadpool.keys(); foreach(QThread *pth,lstThreads) { if (minLoad>m_map_threadpool[pth].size()) { minLoad = m_map_threadpool[pth].size(); bestTh = pth; } } Q_ASSERT(bestTh); node->moveToThread(bestTh); m_map_threadpool[bestTh].insert(node); //关联各个事件 Associating individual events connect (node, &taskNode::sig_new_package, this, &taskProject::slot_new_package,Qt::QueuedConnection); connect (node, &taskNode::sig_new_command, this, &taskProject::slot_new_command,Qt::QueuedConnection); connect (node, &taskNode::sig_new_errmsg, this, &taskProject::slot_new_msg,Qt::QueuedConnection); connect (node, &taskNode::sig_pro_started, this, &taskProject::slot_pro_started,Qt::QueuedConnection); connect (node, &taskNode::sig_pro_stopped, this, &taskProject::slot_pro_stopped,Qt::QueuedConnection); connect (this, &taskProject::sig_cmd_start, node, &taskNode::cmd_start,Qt::QueuedConnection); connect (this, &taskProject::sig_cmd_stop, node, &taskNode::cmd_stop,Qt::QueuedConnection); connect (this, &taskProject::sig_cmd_write, node, &taskNode::cmd_write,Qt::QueuedConnection); connect (this, &taskProject::sig_cmd_sendcmd, node, &taskNode::cmd_sendcmd,Qt::QueuedConnection); connect (node, &taskNode::sig_iostat, this, &taskProject::sig_iostat); //回调额外的索引创建事件 Callback for additional index creation events m_fInsAppended(mod,node,pt); if (rebuildidx) this->refresh_idxes(); } } void taskProject::del_node(int node) { int sz = m_vec_nodes.size(); if (node>=0 && node < sz) { foreach (QThread * t, m_map_threadpool.keys()) m_map_threadpool[t].remove(m_vec_nodes[node]); const QString func = m_vec_cells[node]->function_firstname(); unsigned int instanceid = m_vec_cells[node]->function_instance(func); unreg_instance(instanceid); //清理节点 m_vec_nodes[node]->deleteLater(); if (node>=0) { QObject * obj = dynamic_cast (m_vec_cells[node]); if (!obj) delete m_vec_cells[node]; else obj->deleteLater(); } m_vec_nodes.remove(node); m_vec_cells.remove(node); } else { for (int i=0;ifunction_firstname(); unsigned int instanceid = m_vec_cells[i]->function_instance(func); unreg_instance(instanceid); //清理节点 m_vec_nodes[i]->deleteLater(); if (node>=0) { QObject * obj = dynamic_cast (m_vec_cells[i]); if (!obj) delete m_vec_cells[i]; else obj->deleteLater(); } } m_vec_nodes.clear(); m_vec_cells.clear(); } this->refresh_idxes(); } /*! * \brief taskProject::set_outside_id_in 仅在本Project作为子项目时有用 * 用来设置外部的专题(管脚)ID * Useful only when this project is a subproject. * Used to set the external Subject (PIN) ID * \param name 悬空管脚(专题)名 Subject Name * \param ins 悬空管脚(专题)ID Subject ID */ void taskProject::set_outside_id_in (QString name, unsigned int ins) { if (idxout_hang_fullname2in().keys().contains(name)) { m_outside_name2id_in[name] = ins; refresh_idxes(); } } /*! * \brief taskProject::set_outside_id_out 仅在本Project作为子项目时有用 * 用来设置外部的专题(管脚)ID * Useful only when this project is a subproject. * Used to set the external Subject (PIN) ID * \param name 悬空管脚(专题)名 Subject Name * \param ins 悬空管脚(专题)ID Subject ID */ void taskProject::set_outside_id_out (QString name, unsigned int ins) { if (idxout_hang_fullname2out().keys().contains(name)) { m_outside_name2id_out[name] = ins; refresh_idxes(); } } /*! * \brief taskProject::refresh_idxes 根据各个专题的ID,构件索引 * ID Widget index based on each topic */ void taskProject::refresh_idxes() { LOG_PROFILE("CORE","rebuild indexes."); m_idx_instance2vec.clear(); m_idx_in2instances.clear(); m_idx_in2names.clear(); m_idx_out2instances.clear(); m_idx_out2names.clear(); m_idx_node2vec.clear(); QSet used_ids; int sizeV = m_vec_nodes.size(); //for each nodes , do for (int i=0;ifunction_names(); if (lstfuns.size()!=1) continue; QString func = lstfuns.first(); unsigned int instanceid = model->function_instance(func); //record map from instanceid to order (i) m_idx_instance2vec[instanceid] = i; //in subjects QStringList lstSrcSubs = model->in_subjects(func); foreach (QString bname,lstSrcSubs ) { unsigned int subid = model->in_subject_instance(func,bname); if (subid) { m_idx_in2instances[subid].push_back(instanceid); m_idx_in2names[subid].push_back(bname); used_ids.insert(subid); } } //out subjects QStringList lstOutSubs = model->out_subjects(func); foreach (QString bname,lstOutSubs ) { unsigned int subid = model->out_subject_instance(func,bname); if (subid) { m_idx_out2instances[subid].push_back(instanceid); m_idx_out2names[subid].push_back(bname); used_ids.insert(subid); } } } //悬空管脚索引创建。悬空管脚作为整体工程对外的接口。 //The dangling pin index will be created. The dangling pin is an //external interface for the whole project. m_hang_in2instance.clear(); m_hang_in2name.clear(); m_hang_in2fullname.clear(); m_hang_fullname2in.clear(); m_hang_fullname2out.clear(); m_hang_out2instance.clear(); m_hang_out2name.clear(); m_hang_out2fullname.clear(); if (m_bWrapper) { unsigned int start_test_id= 1; for (int i=0;ifunction_names(); if (lstfuns.size()!=1) continue; QString func = lstfuns.first(); unsigned int instanceid = model->function_instance(func); //in QStringList lstSrcSubs = model->in_subjects(func); foreach (QString bname,lstSrcSubs ) { unsigned int subid = model->in_subject_instance(func,bname); if (!subid) { while (used_ids.contains(start_test_id)) ++start_test_id; used_ids.insert(start_test_id); m_hang_in2instance[start_test_id] = instanceid; m_hang_in2name[start_test_id] = bname; QString fulln = m_hang_in2fullname[start_test_id] = func+"_"+ bname + QString("i%1").arg(instanceid); m_hang_fullname2in[ fulln] = start_test_id; } } //out QStringList lstOutSubs = model->out_subjects(func); foreach (QString bname,lstOutSubs ) { unsigned int subid = model->out_subject_instance(func,bname); if (!subid) { while (used_ids.contains(start_test_id)) ++start_test_id; used_ids.insert(start_test_id); m_hang_out2instance[start_test_id] = instanceid; m_hang_out2name[start_test_id] = bname; QString fulln = m_hang_out2fullname[start_test_id] = func+"_"+ bname + QString("o%1").arg(instanceid); m_hang_fullname2out[ fulln] = start_test_id; } } } } //内外映射 internal and external mapping m_iface_inside2outside_in.clear(); m_iface_inside2outside_out.clear(); m_iface_outside2inside_in.clear(); m_iface_outside2inside_out.clear(); if (m_bWrapper) { QList inside_ins_ins = m_hang_in2fullname.keys(); foreach (unsigned int in, inside_ins_ins) { const QString fullname = m_hang_in2fullname[in]; if (m_outside_name2id_in.contains(fullname)) { m_iface_inside2outside_in[in] = m_outside_name2id_in[fullname]; m_iface_outside2inside_in[m_outside_name2id_in[fullname]] = in; } } QList inside_ins_outs = m_hang_out2fullname.keys(); foreach (unsigned int out, inside_ins_outs) { const QString fullname = m_hang_out2fullname[out]; if (m_outside_name2id_out.contains(fullname)) { m_iface_inside2outside_out[out] = m_outside_name2id_out[fullname]; m_iface_outside2inside_out[m_outside_name2id_out[fullname]] = out; } } } //回调函数,用来通知图形界面刷新。 //callback function to notify the graphical interface to refresh. m_fIndexRefreshed(); LOG_PROFILE("CORE","rebuild indexes finished."); } /*! * \brief taskProject::toJson conver to JSON * \return JSON string in UTF-8 */ QByteArray taskProject::toJson() { QJsonObject obj_root; obj_root["total_mods"] = m_vec_cells.size(); int nModels = m_vec_cells.size(); for (int nmodidx = 0;nmodidxtoJson("")); obj_root[key] = doc.object(); //位置 QPointF pf = m_fGetCellPos(nmodidx); QJsonObject posobj; posobj["x"] = pf.x(); posobj["y"] = pf.y(); key = QString("pos%1").arg(nmodidx); obj_root[key] = posobj ; } QJsonDocument doc(obj_root); return doc.toJson(QJsonDocument::Indented); } /*! * \brief taskProject::fromJson Fill project from json * \param json JSON project ,from file *.tbj * \param m_pRefModel 场景中可用的模块列表。 * A list of modules available in the scene. */ void taskProject::fromJson(QByteArray json, taskCell * m_prefCell) { QJsonDocument doc = QJsonDocument::fromJson(json); QJsonObject obj_root = doc.object(); if (obj_root.isEmpty()) return; int insts = obj_root["total_mods"].toInt(); for(int i=0;ifunction_names().contains(funcName)==false) { qDebug()<function_exec(funcName); md.set_function_exec(funcName,insPath); key = QString("pos%1").arg(i); double fx = obj_root[key].toObject()["x"].toDouble(); double fy = obj_root[key].toObject()["y"].toDouble(); add_node(md.toJson(funcName),QPointF(fx,fy),false); } refresh_idxes(); } QString taskProject::cmdlinePrg(taskCell * model) { QString cmdline; const QStringList functions = model->function_names(); if (functions.empty()) return cmdline; const QString func = functions.first(); unsigned int func_ins = model->function_instance(func); if (func_ins==0) return cmdline; return model->function_exec(func); } QStringList taskProject::cmdlineParas(taskCell * model) { QStringList lst; const QStringList functions = model->function_names(); if (functions.empty()) return lst; const QString func = functions.first(); unsigned int func_ins = model->function_instance(func); if (func_ins==0) return lst; //参数,传入进程实例ID parameters, incoming process instance ID lst<parameters(func); foreach (const QString paraname,paranames) { const QVariant v = model->parameters_instance(func,paraname); if (v.isValid()) { switch(v.type()) { case QVariant::Double: { lst<internal_to_view(v).toDouble(),0,'g',15); break; } default: lst<internal_to_view(v).toString()); break; } } } //传入各个输入输出管脚(专题)的instance //Incoming instance for each input/output pin (special subject) const QStringList in_subs = model->in_subjects(func); foreach (const QString subname,in_subs) { const unsigned int v = model->in_subject_instance(func,subname); QString fulln = func+"_"+ subname + QString("i%1").arg(func_ins); if (v>0) lst<out_subjects(func); foreach (const QString subname,out_subs) { const unsigned int v = model->out_subject_instance(func,subname); QString fulln = func+"_"+ subname + QString("o%1").arg(func_ins); if (v>0) lst<(pkg.size())(pkg.constData()); if (header->data_length+sizeof( TASKBUS::subject_package_header)!=static_cast(pkg.size())) continue; bool blocked = false; try { taskNode * pNodeSrc = qobject_cast(sender()); if (!pNodeSrc) throw "pNodeSrc is not sender() type"; if (m_idx_node2vec.contains(pNodeSrc)==false) throw "node idx does not contain sender"; int nvecidx = m_idx_node2vec[pNodeSrc]; taskCell * mod = m_vec_cells[nvecidx]; QStringList srcfuns = mod->function_names(); if (srcfuns.size()==0) throw "srcfuns.size() is 0"; //看看是否合法 See if it's legal. if (header->subject_id!=TB_SUBJECT_CMD) { quint32 src_inst = mod->function_instance(srcfuns.first()); //专题是否被登记为内部专题 //Whether the subject was registered as an internal topic if (m_idx_out2instances.contains(header->subject_id)==true) { //是否为本专题合法生产者 //Whether it is a legitimate producer of this topic if (m_idx_out2instances[header->subject_id].contains(src_inst)==false) throw tr("source instance %1 is not a valid producer for subject %2.") .arg(src_inst) .arg(header->subject_id); //专题是否被登记 //Whether the subject has registered consumers if (m_idx_in2instances.contains(header->subject_id)==false) throw tr("input subject %1 has no valid recievers.") .arg(header->subject_id); //是否为合法头部 legal head if (!(header->prefix[0]!=0x3C || header->prefix[1]!=0x5A || header->prefix[2]!=0x7E || header->prefix[3]!=0x69)) { //传输给所有消费者 Transfer to all consumers foreach (quint32 uins, m_idx_in2instances[header->subject_id] ) { if (m_idx_instance2vec.contains(uins)==false) continue; int bidx = m_idx_instance2vec[uins]; emit sig_cmd_write(m_vec_nodes[bidx],pkg); //有接收者阻塞了 There's a receiver blocking it. if (m_vec_nodes[bidx]->outputQueueSize()>16) blocked = true; } //防止过度缓存耗尽内存。 //Prevents excessive cache depletion of memory. pNodeSrc->setBlockFlag(blocked); } } //专题是否被登记为外部专题 //Whether the topic was registered as an external topic else if (m_hang_out2instance.contains(header->subject_id)==true && m_bWrapper==true) { //是否为本专题合法生产者 //Whether it is a legitimate producer of this topic if (m_hang_out2instance[header->subject_id]==src_inst) { //专题名字获取 Topic name Acquisition QString strFullName = m_hang_out2fullname[header->subject_id]; //专题是否需要向外发射 Whether the topic needs to be launched outward if (m_outside_name2id_out.contains(strFullName)==true&& !(header->prefix[0]!=0x3C || header->prefix[1]!=0x5A || header->prefix[2]!=0x7E || header->prefix[3]!=0x69)) { TASKBUS::subject_package_header * wrheader = reinterpret_cast(pkg.data()); wrheader->subject_id = m_outside_name2id_out[strFullName]; //发送 Transmit emit sig_outside_new_package(pkg); } } } else throw tr("output subject \"%1\" does not exits.").arg(header->subject_id); } else { //指令处理 Instruction processing //! It will be dealed in each nodes' thread. Q_ASSERT(false); } } catch(QString msg) { push_msg(msg); } catch(const char * msg) { push_msg(msg); } if (blocked) push_msg(QString("Blocked by later process.")); } LOG_PROFILE("IO","End Dealing packs."); } /*! * \brief taskProject::slot_new_command commands is another way to handover messages. * \param cmd message. * \details * taskbus支持跨模块的消息。消息由分号分割的键-值序列组成。以下三个保留的键名包括: * 1.source 来源模块的标识。标识的值由模块自身定义并在手册中声明。建议采用UUID或者全域名。 * 2.destin 目的模块的标识。可以有多组。ALL表示向所有模块发送。 * 3.function 功能名。 * 其他参数任意指定。 * taskBus support messages over modules. messages is a set of key-value pairs, * which is splitted by ";". Key-value are connected with "=". * There are 3 reserved keywords: * 1.source: ID of source module. ID is given by each module designer, UUID or * full domain name is strongly recommanded. * 2.destin: ID of destin modules. "0" means all modules. module names are seperated by "," * 3.function: function name. * * eg: * soucre=fft.ghstudio.org;destin=detector.clip.wav,plots.3dshow;function=spec_append;size=1024; * means: * source is from fft.ghstudio.org * destin is to detector.clip.wav and plots.3dshow * function is spec_append * other parameters: size=1024 */ void taskProject::slot_new_command(QMap cmd) { emit sig_cmd_display(cmd); if (cmd.size()) { QString source; if (cmd.contains("source")) source = cmd["source"].toString().trimmed(); else return; if (cmd.contains("destin")) { const QStringList destins = cmd["destin"].toString().split(","); QSet notified; foreach (QString destinstr, destins) { const QString des = destinstr.trimmed(); if (des!=source) notified.insert(des); } emit sig_cmd_sendcmd(cmd,notified); } else return; } } /*! * \brief PDesignerView::slot_new_errmsg 新的输出日志 New output Log * \param msg 日志体 Log body */ void taskProject::slot_new_msg(QByteArrayList msgs) { taskNode * pNodeSrc = qobject_cast(sender()); if (!pNodeSrc) { send_msg(QString("Project:"),msgs); return; } if (m_idx_node2vec.contains(pNodeSrc)==false) { send_msg(QString("Node%1:").arg((quint64)pNodeSrc),msgs); return; } int nvecidx = m_idx_node2vec[pNodeSrc]; taskCell * mod = m_vec_cells[nvecidx]; QStringList srcfuns = mod->function_names(); if (srcfuns.size()==0) { send_msg(QString("Node%1:").arg((quint64)pNodeSrc),msgs); return; } quint32 srcins = mod->function_instance(srcfuns.first()); QString smsg = srcfuns.first() + QString("(%1):").arg(srcins); send_msg(smsg,msgs); } /*! * \brief PDesignerView::slot_pro_started 进程已经启动 * Process has started */ void taskProject::slot_pro_started() { taskNode * pNodeSrc = qobject_cast(sender()); if (!pNodeSrc) return; if (m_idx_node2vec.contains(pNodeSrc)==false) { return; } int nvecidx = m_idx_node2vec[pNodeSrc]; taskCell * mod = m_vec_cells[nvecidx]; QStringList srcfuns = mod->function_names(); if (srcfuns.size()==0) return; quint32 srcins = mod->function_instance(srcfuns.first()); QString smsg = srcfuns.first() + QString("(%1):").arg(srcins); smsg += "Started."; push_msg(smsg); } void taskProject:: slot_pro_stopped() { taskNode * pNodeSrc = qobject_cast(sender()); if (!pNodeSrc) return; if (m_idx_node2vec.contains(pNodeSrc)==false) { return; } int nvecidx = m_idx_node2vec[pNodeSrc]; taskCell * mod = m_vec_cells[nvecidx]; QStringList srcfuns = mod->function_names(); if (srcfuns.size()==0) return; quint32 srcins = mod->function_instance(srcfuns.first()); QString smsg = srcfuns.first() + QString("(%1):").arg(srcins); smsg += "Stopped."; push_msg(smsg); } void taskProject::start_project() { QSettings settings(QCoreApplication::applicationFilePath()+".ini",QSettings::IniFormat); int pr = settings.value("settings/nice",TASKBUS::pnice_norm).toInt(); TASKBUS::set_proc_nice(pr); settings.setValue("settings/nice",pr); int bt = settings.value("settings/batchtime",taskCell::default_batchtime).toInt(); taskCell::default_batchtime = bt; settings.setValue("settings/batchtime",taskCell::default_batchtime); if (m_bRunning) return; int ns = m_vec_nodes.size(); for (int i=0;icmdlinePrg(m_vec_cells[i]); QStringList lstp = this->cmdlineParas(this->m_vec_cells[i]); emit sig_cmd_start(m_vec_nodes[i],cmd,lstp); } m_bRunning = true; emit sig_started(); } /*! * \brief taskProject::stop_project * GUI app please use void taskProject::stop_project(QThread * pIdelThread) */ void taskProject::stop_project() { if (m_bRunning==false) return; int ns = m_vec_nodes.size(); for (int i=0;iisRunning()?1:0; QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QThread::msleep(50); }while (nrun); TASKBUS::set_proc_nice(TASKBUS::pnice_norm); emit sig_stopped(); m_bRunning = false; } /*! * \brief taskProject::stop_project * \param pIdelThread GUI thread for GUI apps. * 为了保证密集的IO不会阻塞界面,每个工程的IO吞吐是在独立的线程运行的。 * 由于工程本身又和GUI相关,因此在工程启动时,事件会被“转移(moveToThread)” * 到独立线程;工程结束运行,则重新回到GUI线程。 * To ensure that dense IO does not block the interface, IO throughput for * each project runs on a separate thread. Because the project itself is related * to the GUI, when the project starts, the event is "transferred (Movetothread)" * to the stand-alone thread, and when the project is finished running, * it returns to the GUI thread. */ void taskProject::stop_project(QThread * pIdelThread) { if (m_bRunning==false) return; int ns = m_vec_nodes.size(); for (int i=0;iisRunning()?1:0; QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); QThread::msleep(50); }while (nrun); TASKBUS::set_proc_nice(TASKBUS::pnice_norm); moveToThread(pIdelThread); emit sig_stopped(); m_bRunning = false; } /*! * \brief taskProject::default_NewCell 默认的模块工厂。 * 注意,在图形化界面里,taskCell会派生出支持图形化设计的子类taskModule * The default module factory. * Note that in a graphical interface, Taskcell will derive a subclass * that supports graphical design taskmodule * \return 新建的模块运行时对象。The new module run-time object. */ taskCell * taskProject::default_NewCell() { return new taskCell(); } /*! * \brief taskProject::default_InsAppended 默认的后续创建初始化函数 * Default subsequent creation of the initialization function * \param pmod 创建的模块 The module created * \param pnod 模块对应的运行时 The runtime of the corresponding module * \param pt 模块位置 Module graphics location */ void taskProject::default_InsAppended(taskCell * /*pmod*/, taskNode * /*pnod*/,QPointF /*pt*/) { } void taskProject::default_Indexrefreshed() { } QPointF taskProject::default_GetCellPos(int n) { int row = n / 4; return QPointF((n%4)*100+100,row * 200+100); } /*! * \brief taskProject::slot_outside_send 收到了从外部得到的数据包 * Received a packet from the outside * \param node 是不是给本节点的 whether or not given to this node * \param arr 数据包 package */ void taskProject::slot_outside_recieved(QByteArray pkg) { if (static_cast(pkg.size())(pkg.constData()); if (header->data_length+sizeof( TASKBUS::subject_package_header)!=static_cast(pkg.size())) return; try { if (header->subject_id!=TB_SUBJECT_CMD) { //进行解析、转发 To parse, forward if (m_iface_outside2inside_in.contains(header->subject_id)==false) throw tr("No valid inside maps for inid %1 .").arg(header->subject_id); unsigned int intenal_in_id = m_iface_outside2inside_in[header->subject_id]; //专题是否被登记为内部专题 Whether the topic was registered as an internal topic if (m_hang_in2instance.contains(intenal_in_id)==true) { //是否为合法 Whether it is legal if (!(header->prefix[0]!=0x3C || header->prefix[1]!=0x5A || header->prefix[2]!=0x7E || header->prefix[3]!=0x69)) { TASKBUS::subject_package_header * wrheader = reinterpret_cast(pkg.data()); wrheader->subject_id = intenal_in_id; //广播 transmit int bidx = m_idx_instance2vec[m_hang_in2instance[intenal_in_id]]; emit sig_cmd_write(m_vec_nodes[bidx],pkg); } } else throw tr("outside input subject \"%1\" does not exits.").arg(header->subject_id); } else { //信令 const char * cmd = pkg.constData() + sizeof( TASKBUS::subject_package_header); QString dac = QString::fromUtf8(cmd,header->data_length); QMap vt_map = taskCell::string_to_map(dac); slot_new_command(vt_map); } } catch(QString msg) { push_msg(msg); } catch(const char * msg) { push_msg(QString(msg)); } } void taskProject::turnOnDebug(int nidx) { if (nidx>=0 && nidxsetDebug(true); } void taskProject::turnOffDebug(int nidx) { if (nidx>=0 && nidxsetDebug(false); } int taskProject::get_nice(int nidx) const { int nice = 2; if (nidx>=0 && nidx addArgs = m_vec_cells[nidx]->additional_paras(m_vec_cells[nidx]->function_firstname()); if (addArgs.contains("nice")) nice = addArgs["nice"].toInt(); } return nice; } int taskProject::set_nice(int nidx,int nice) { if (nidx>=0 && nidx addArgs = m_vec_cells[nidx]->additional_paras(m_vec_cells[nidx]->function_firstname()); addArgs["nice"] = nice; m_vec_cells[nidx]->set_additional_paras(m_vec_cells[nidx]->function_firstname(),addArgs); } return nice; } void taskProject::timerEvent(QTimerEvent * evt) { if (evt->timerId()==m_nTimerID) flush_msg(); QObject::timerEvent(evt); } void taskProject::push_msg(QString smsg) { m_bufferMsgs.push_back(QByteArray::fromStdString(smsg.toStdString())); m_bufferMsgSources.push_back(QString("Project:")); } void taskProject::send_msg(QString smsgSource, QByteArrayList lst) { static clock_t last_ck = clock(); //Prevent of too short freq. clock_t curr_ck = clock(); bool keep = false; if (curr_ck-last_ck <=CLOCKS_PER_SEC/10 && curr_ck-last_ck>=0) keep = true; last_ck = curr_ck; const int szMsgs = lst.size(); for(int i=0;i