-
过年几天研究了一下python脚本的集成
通过集成python脚本可以实现python调用寄主所提供的大量函数,同时也能通过pip增加python功能而被寄主调用,这样的确不错,很多业务也可以用python来做进行一些测试工作;昨天突然发现2年前自己写的c++调用c#脚本的功能跟unity的实现好多不谋而合,要是有unity源码看看就好,我在自定义类型返回时候的处理还是没想到好办法,毕竟这个类型还跨语言;如果这个解决个人觉得c++配c#脚本还是很香。
-
雏形简介
上位机框架雏形介绍20221126yes@she.vin一、雏形原始目标:实现通用硬件管理系统;实现业务逻辑管理系统;实现环境语言:qt5;实现周期2个月;实现模式单人; 实际实现细节:实际实现已完全达成目标,并增加很多周边配套功能,基本可以用于项目开发,有待项目验证。a.硬件管理系统具体功能 实现硬件以插件方式替换的功能,在业务功能不变情况下随机更换底层运动卡硬件插件,而无需做任何编程工作即可完成对整个项目硬件层面的调整;减少对各种卡的熟悉时间成本,及卡本身的成本,使开发使用人员不用关心硬件层面的实现,能专注于业务功能实现,快速应对项目;(当前仅实现运动控制卡及io卡的上层管理,后续将增加PLC,扫码枪,机器人,光源控制器,CCD,高速模拟量模块等); 在项目硬件未确认情况下即可用虚拟卡进行项目的业务逻辑开发,而无需关心控制硬件是否已选定,便于早期调试,业务验证,可以改变传统的选硬件出电气图,确认轴,气缸等的接线后才能开始编程的模式,以一种全新的姿态去做项目,可以高节奏高效率的去开展工作;(本人曾经用自己写的PYTHON 版的上位机框架同时做5个项目,这在几年前是不敢想也不敢操作的); 支持硬件配置文件的一键导入导出功能,整个能快速打通电气与软件之间的壁垒;电气在整理BOM表的时候字段按我们提供的excel格式即可一次操作多方使用;无论是硬件确认没确认给硬件一个符号代号即可;也可以减少部门间因为叫法定义偏差而造成的沟通成本; 支持硬件调试,可以将硬件管理模块独立输出成小工具供电气处理阶段的调试辅助,便于快速对IO,调电机等;配置信息可在后续直接使用,便于将整个开发过程串通起来,减少低效沟通带来的时间成本;硬件插件可默认采用通用界面,后续留有扩展可自动识别用户自定义界面,便于特殊硬件的特殊处理; B.业务管理框架1.为完善本模块又编写了一套变量管理系统,支持实时监控,变量,同时为业务插件间交互提供了可靠的方式;2.业务模块可随编写者心意,自由定义功能、功能涉及实现步骤排序、跳转、监控、旁通、单步等;3.每个业务模块只需要实现组成不用关心业务控制,系统会自动分配线程池去关联并组织运行; C.整体特点1.所有项目开发不用公开任何框架源码实现,仅依靠头文件和功能介绍即可,减少耦合与实现的弊端。开发者可以将整个框架当作一个全功能的函数库,按常规模式开发,不用框架的业务管理自己按底层支持函数,开发自己的业务管理部分,自己的硬件管理界面;完全做到无任何限制,任意定义自己的软件框架结构;如果想偷懒就用系统默认框架,如果想玩界面就自己写界面插件,如果不认可所有已有框架界面就当个全功能函数库来用,自己写配置界面和软件整体界面,以及其他任意界面;可大可小伸缩性极强;2.支持32位,64位,release,debug模式的自动调用,只需要编译不同模式的主引导程序即可,环境适配性强;3.如果用自定义界面可以不用开放ZKHY.exe,按规则写好界面插件放置到UI目录后则自动调整为用户的自定义界面; 具体项目开发步骤导入电气按格式输出的项目元器件到项目;创建虚拟控制卡,匹配导入硬件命名即可;进行业务模块开发(进行无实卡模式调试);待开发完成后,修改虚拟卡配置为实际使用卡;上机验证(由于基于接口方式,虚拟卡能正常的,实体卡在封装正确的情况下一定正确,几乎验证不花时间);业务逻辑单步测试;单个任务整体测试;整机任务测试;交机;
-
有些心得刚好一致,如此懒得再写
C++ STL容器如何解决线程安全的问题? 原创 众所周知,STL容器不是线程安全的。对于vector,即使写方(生产者)是单线程写入,但是并发读的时候,由于潜在的内存重新申请和对象复制问题,会导致读方(消费者)的迭代器失效。实际表现也就是招致了core dump。另外一种情况,如果是多个写方,并发的push_back(),也会导致core dump。 解法一: 加锁是一种解决方案,但是加std::mutex互斥锁确实性能较差。对于多读少写的场景可以用读写锁(也叫共享独占锁),来缓解。C++17引入了std::shared_mutex 。更多锁的种类可以阅读下面这篇文章,但是本文的目的自然不是自我重复再次介绍一次锁的使用,请继续阅读解法二! https://blog.csdn.net/guodongxiaren/article/details/120799601https://blog.csdn.net/guodongxiaren/article/details/120799601 解法二: 更多的时候,其实可以通过固定vector的大小,避免动态扩容(无push_back)来做到lock-free! 即在开始并发读写之前(比如初始化)的时候,给vector设置好大小。structData {…};vector<Data> v;v.resize(1000); 注意是resize,不是reserve! 可能大家平时用reserve()比较多,顾名思义,reserve就是预留内存。为的是避免内存重新申请以及容器内对象的拷贝。说白了,reserve()是给push_back()准备的! 而resize除了预留内存以外,还会调用容器元素的构造函数,不仅分配了N个对象的内存,还会构造N个对象。从这个层面上来说,resize()在时间效率上是比reserve()低的。但是在多线程的场景下,用resize再合适不过。 你可以resize好N个对象,多线程不管是读还是写,都是通过容器的下标访问【operator[]】来访问元素,不要push_back新元素。所谓的『写操作』在这里不是插入新元素,而是修改旧元素。 如果N的最大个数是可以预期的就直接设置就好,如果没办法预期就再把vector搞成ring buffer(环形队列)来缓解压力。 可以给元素类加上成员变量标记当前的读写状态、是否被消费等等。 当然,你会说,如果B,C,D,E,F这个5个线程是等价的,要不停消费vector中的元素,会造成重复消费不? 当然会。你可以把 队列头的下标定义程原子变量(std::atomic),尽管原子变量也需要做线程同步,但是比一般的锁开销要小很多啦。 如果你想连原子变量也不用,有没有办法呢?有啊。那就给B,C,D,E,F分配不同的消费队列啊。比如当前有5个读线程,那么每个线程就消费下标模5之后的某个固定结果的下标。比如: B消费:0、5、10、15、…… C消费:1、6、11、16、…… D消费:2、7、12、17、…… E消费:3、8、13、18、…… F消费:4、9、14、19、…… 每个读线程各自维护自己当前消费的最新下标。 这样做有啥问题没?也有,就是可能会导致不同的线程繁忙和等待的情况差异巨大:忙的忙死,闲的闲死。具体场景具体分析,总之,无论如何要控制住。不要让一个任务hang住整个线程。 关联容器的线程安全问题 vector是顺序容器,STL中还有一类关联容器其线程安全问题也不容小觑。比如map、unordered_map。 我们可能会有这样一种场景:在并发环境下,收集一些Key-Value,存储在某一个公共的容器中。这里也谈一下不用锁的方案,当然做不到放之四海皆准。它有一些限制条件,只能看是否满足你的需要了。 当有多个写线程对情况下,并发地插入 map/unordered_map都会引发core dump。对此,在某些场景下也可以避免加锁:如果全量的key有办法在并发之前就能拿到的,那么就对这个map,提前做一下insert。并发环境中如果只是修改value,而不是插入新key就不会core dump!不过如果你没办法保证多个写线程不会同时修改同一个key的value,那么可能存在value的覆盖。无法保证这点时,还是需要加锁。不过可以对key采取某种hash策略转成整型,然后进行分段加锁,减少一点锁冲突的概率,或者用一下CAS的策略。
-
std::vector和std::map读写安全验证问题
STL 语义上不提供任何强度的线程安全保证。 1、vector与map都不是线程安全的:同时读OK同时写NO== 同时读写==NO 2、vector读写情况:vector一般情况下同时读写读没问题,但当vector预留内存空间不足,需要扩容导致的变量搬移时,读存在问题,同时写也存在问题,因此需要加锁,防止并发执行。 3、map读写情况:map底层结构时红黑树,每插入一个节点,map对下中数据分布就会变,因此,不可以同时写、也不能同时读写。 参考资料:1、C++ STL容器如何解决线程安全的问题?2、[C/C++标准库][初级][std::vector的多线程读写问题]·
-
share_ptr加入stl
#include <string>#include <vector>#include <memory>#include <map> template <class T>using SPVEC = std::vector<std::shared_ptr<T>>; template <class T1, class T2>using SPMAP = std::map<T1, std::shared_ptr<T2>>; const size_t LEN = 1024 * 1024 ; class TestUnit{public: TestUnit(int _id); ~TestUnit(); private: int m_id; std::string m_buf;}; TestUnit::TestUnit(int _id):m_id(_id){ m_buf.resize(LEN, 0); printf(“%d construction\n”,m_id);} TestUnit::~TestUnit(){ printf(“%d destruction\n”, m_id);} int main(int argc, char** argv) { { […]