VRSProcess(二)
1._beginthreadex再谈
Windows操作系统提供了这样的一种解决方案——每个线程都将拥有自己专用的一块内存区域来供标准C运行库中所有有需要的函数使用。而且这块内存区域的创建就是由C/C++运行库函数_beginthreadex()来负责的。
_beginthreadex()函数在创建新线程时会分配并初始化一个_tiddata块。这个_tiddata块自然是用来存放一些需要线程独享的数据。事实上新线程运行时会首先将_tiddata块与自己进一步关联起来。然后新线程调用标准C运行库函数如strtok()时就会先取得_tiddata块的地址再将需要保护的数据存入_tiddata块中。这样每个线程就只会访问和修改自己的数据而不会去篡改其它线程的数据了。因此,如果在代码中有使用标准C运行库中的函数时,尽量使用_beginthreadex()来代替CreateThread()。
handle = (HANDLE)_beginthreadex(NULL, 0, ThreadFun, NULL, 0, NULL);
函数说明:
第一个参数表示线程内核对象的安全属性,一般传入NULL表示使用默认设置。
第二个参数表示线程栈空间大小。传入0表示使用默认大小(1MB)。
第三个参数表示新线程所执行的线程函数地址,多个线程可以使用同一个函数地址。
第四个参数是传给线程函数的参数。
第五个参数指定额外的标志来控制线程的创建,为0表示线程创建之后立即就可以进行调度,如果为CREATE_SUSPENDED则表示线程创建后暂停运行,这样它就无法调度,直到调用ResumeThread()。
第六个参数将返回线程的ID号,传入NULL表示不需要返回该线程ID号。
函数返回值:
成功返回新线程的句柄,失败返回NULL
---------------------
作者:MoreWindows
来源:CSDN
原文:https://blog.csdn.net/morewindows/article/details/7421759
版权声明:本文为博主原创文章,转载请附上博文链接!
WaitForSingleObject
函数功能:等待函数 – 使线程进入等待状态,直到指定的内核对象被触发。
函数原形:
DWORDWINAPIWaitForSingleObject(
HANDLEhHandle,
DWORDdwMilliseconds
);
函数说明:
第一个参数为要等待的内核对象。
第二个参数为最长等待的时间,以毫秒为单位,如传入5000就表示5秒,传入0就立即返回,传入INFINITE表示无限等待。
因为线程的句柄在线程运行时是未触发的,线程结束运行,句柄处于触发状态。所以可以用WaitForSingleObject()来等待一个线程结束运行。
函数返回值:
在指定的时间内对象被触发,函数返回WAIT_OBJECT_0。超过最长等待时间对象仍未被触发返回WAIT_TIMEOUT。传入参数有错误将返回WAIT_FAILED
---------------------
作者:MoreWindows
来源:CSDN
原文:https://blog.csdn.net/morewindows/article/details/7421759
版权声明:本文为博主原创文章,转载请附上博文链接!
2.WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
函数原型为: DWORD WaitForMultipleObjects( DWORD nCount, // number of handles in the handle array CONST HANDLE *lpHandles, // pointer to the object-handle array BOOL fWaitAll, // wait flag DWORD dwMilliseconds // time-out interval in milliseconds );
参数解析:
DWORD 就是 Double Word, 每个word为2个字节的长度,DWORD双字即为4个字节,每个字节是8位。
nCount 指定列表中的句柄数量 最大值为MAXIMUM_WAIT_OBJECTS(64)
*lpHandles 句柄数组的指针。lpHandles为指定对象句柄组合中的第一个元素 HANDLE类型可以为(Event,Mutex,Process,Thread,Semaphore)数组
bWaitAll 等待的类型,如果为TRUE,表示除非对象都发出信号,否则就一直等待下去;如果FALSE,表示任何对象发出信号即可
dwMilliseconds指定要等候的毫秒数。如设为零,表示立即返回。如指定常数INFINITE,则可根据实际情况无限等待下去
---------------------
作者:sac761
来源:CSDN
原文:https://blog.csdn.net/sac761/article/details/52456385
版权声明:本文为博主原创文章,转载请附上博文链接!
3.CreateEvent 参见:C++进阶—>CreateEvent控制线程 另一个:https://blog.csdn.net/swartz_lubel/article/details/61630022
另:秒杀多线程:https://blog.csdn.net/morewindows/article/details/7445233
CreateEvent是创建windows事件的意思,作用主要用在判断线程退出,线程锁定方面。
EVENT有两种状态:发信号,不发信号。
SetEvent/ResetEvent分别将EVENT置为这两种状态分别是发信号与不发信号。
WaitForSingleObject()等待,直到参数所指定的OBJECT成为发信号状态时才返回,OBJECT可以是EVENT,也可以是其它内核对象。
这里先介绍:采用事件的方式来通知从线程运行函数退出来,它的实现原理是这样,在那个死循环里不断地使用 WaitForSingleObject函数来检查事件是否满足,如果满足就退出线程,不满足就继续运行。当在线程里运行阻塞的函数时,就需要在退出线程 时,先要把阻塞状态变成非阻塞状态,比如使用一个线程去接收网络数据,同时使用阻塞的SOCKET时,那么要先关闭SOCKET,再发送事件信号,才可以 退出线程的。
CreateEvent是一个Windows API函数。它用来创建或打开一个命名的或无名的事件对象。如果想为对象指定一个访问掩码,应当使用CreateEventEx函数。
HANDLECreateEvent( LPSECURITY_ATTRIBUTESlpEventAttributes,// 安全属性 BOOLbManualReset,// 复位方式 BOOLbInitialState,// 初始状态 LPCTSTRlpName // 对象名称 );
4.CRITICAL_SECTION
5. InitializeCriticalSection
此函数初始化一个临界区对象。
格式:
void InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection);
参数:lpCriticalSection指向临界区对象的指针。
返回值:无
单个进程的线程可以使用一个互斥同步临界区对象。虽然对线程将获得临界区所有权的顺序没有保证,该系统将处理所有线程的所有权要求。
这个进程负责分配一个临界区对象使用的内存,它可以通过声明类型的CRITICAL_SECTION的变量使用的内存。在使用一个临界区对象以前,一些进程中的线程必须调用InitializeCriticalSection函数来初始化对象。
一旦一个临界区对象已被初始化,该进程的线程可以在EnterCriticalSection或LeaveCriticalSection函数指定对象,提供对共享资源的相互独占式访问。对于不同进程之间的类似线程同步,使用互斥对象。
一个临界区对象不能移动或复制。这一进程也绝不能修改该对象,但必须把它作为逻辑不透明来处理。只能使用由与Microsoft Win32 ® API提供的临界区功能,用来管理临界区对象。
6.map<int, CGGAProc*>
源代码 typedef map<int, CGGAProc*> tGGAPROC; //多个gga线程,多个用户
map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的。
map(有key和value组成)的遍历,和其它STL的容器一样,都是通过迭代器实现的;因此判断value(而不是key)
/******************************************************************************* * 函数名称 : Push * 函数描述 : 将task插入到队列中 * 输入参数 : pTask: 任务对象指针 * 输出参数 : N/A * 返回值 : N/A * 备注 : 多线程操作,需要加锁 * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2012/11/07 3.0 新建 *******************************************************************************/ void Push(T pTask) { ATLock lock(this); m_listTask.push_back(pTask); }
9.理解第六行第七行意思
void CGGAProcMgr::ProcBSData( int iUserId, CPPPFileData* pData ) { //MY_TRACE("CGGAProcMgr::ProcBSData start...\n"); ATLock lock1(m_UserLock); ATLock lock(m_GGAProcLock); int mapkey = iUserId/MAX_GGAPROC_NUM;//线程数量 tGGAPROC::iterator it = m_vecGGAProc.find(mapkey); if (it != m_vecGGAProc.end()) { it->second->PushBSData(iUserId, *pData); } //MY_TRACE("CGGAProcMgr::ProcBSData end...\n"); }
10.
TQueue<CDataForVRS*> m_qDataForVRS; //dataforvrs队列,结构化 list<string> m_lStringForVRS; //dataforvrs队列,序列化的
11.
TQueue<CMSG*> m_qMSG; //任务队列
其中,
struct CMSG { int m_id; string m_strData; CMSG(int id, const char* sz) :m_id(id) ,m_strData(sz) { } ~CMSG() { } protected: CMSG(const CMSG& pObj); CMSG& operator=(const CMSG& pObj); };
12.
//定义模块ID,注册到消息总线 #define MSGSWITCH_MODULE_ID "VRSPROCESS" #define MSGSWITCH_BASESTATION_ID "BaseStationService" #define MSGSWITCH_NTRIPCASTER_ID "NtripCaster" /*******************定义消息回调ID*********************************/ #define MSG_ID_LIVE 0 //心跳 #define MSG_DATA_ID_DATAFORVRS 1 //数据结构DATAFORVRS #define MSG_DATA_ID_NAV 2 //数据结构NavaData #define MSG_DATA_ID_GLONAV 3 //数据结构GloNav #define MSG_BS_COORDINATE 7 //向BaseStation请求基站坐标 #define MSG_DATA_ID_GGA 22 //NtripCaster发来的数据 #define MSG_DATA_ID_USERQUIT 24 //NtripCaster发来的数据 #define MSG_ID_BSSateInfo 30 //发给UI,星空图 #define MSG_DATA_ID_BSINFO 51 //基站信息 #define MSG_B1B2_B1B3 52 //频点选择 #define MSG_SAVE_BASEDATA 28 //基站数据存储 #define MSG_DATA_ID_BSQUIT 53 //基站下线 #define MSG_DATA_ID_NODATAFORVRS 100 //基站解析不到观测数据 /*******************定义消息回调ID**********************************/
13.必须弄懂的关键部分,已懂
/******************************************************************************* * 文件名称 : TaskQueue.h * 作 者 : 3.0 * 创建时间 : 2012/11/07 13:14 * 文件描述 : 任务队列 * 版权声明 : Copyright (C) 2012-2013 联迪恒星(南京)信息系统有限公司 * 修改历史 : 2012/11/07 1.00 初始版本 *******************************************************************************/ #pragma once #include "Lock.h" #include <list> using std::list; template<typename T> class TQueue :public TLock
13.1 list
注意:不能用testiterator.begin()+2来指向list中的第三个对象,因为STL的list是以双链的list来实现的,所有的数据存放不一定是连续存放的。 它不支持随机存取。
c++ 容器(list学习总结)
14.CVRSProcMgr* m_pProcMgr;贯穿全局使用,为主线程
15.解析GGA,后续搜索ParseGGAString,查看调用
BOOL CGGAData::ParseGGAString( string &secondGGA, USERINFO1 &user )
15.1
/******************************************************************************* * 文件名称 : USERINFO1.h * 作 者 : 3.0 * 创建时间 : 2014/11/22 22:56 * 文件描述 : 用户信息结构体 * 版权声明 : Copyright (C) 2014-2015 * 修改历史 : 2014/11/22 1.00 初始版本 *******************************************************************************/ #pragma once #include <string> using namespace std; class USERINFO1
15.2
void CGGAData::ProcBSData( CPPPFileData& ppFileData )
16.在gga中添加高程异常改正
typedef double(CALLBACK*IndexData) (char * BinFile,double B,double L);
同一个类中有:
HINSTANCE hDllInst; HMODULE hDllHeight;
17.查看调用,被(基站?流动站?)
/******************************************************************************* * 函数名称 : InitMsgToCode * 函数描述 : 初始化需编码的数据 * 参数 : * 返回值 : void * 备注 : N/A * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2015/02/14 3.0 新建 * 2015/08/14 3.0 加入PCO修正基准站坐标 *******************************************************************************/ void CGGAData::InitMsgToCode( MsgToCode* v_msgtocode,CPPPFileData *tempData )
18.查看调用
/******************************************************************************* * 函数名称 : ProVRSData() * 函数描述 : 处理VRS数据,注意会用到公共变量m_userInfo * 参数 : * 返回值 : BOOL * 备注 : 返回值为FALSE值是转为SRTK模式 * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2015/03/05 3.0 新建 * 2015/03/09 3.0 修改VRS观测值生成 * 2015/04/23 3.0 修改为大气误差结构体为容器 * 2015/10/21 3.0 修改若离基站距离小于10km,则发送单基站解 *******************************************************************************/ BOOL CGGAData::ProVRSData(int i_BSID, CVRSAtmosChain & v_VRSAtmos)
19.查看调用,虚拟观测值生成
/******************************************************************************* * 函数名称 : DoGenerateVRS() * 函数描述 : 生成VRS观测值 * 参数 : CPPPCellData *tempCellData * 返回值 : void * 备注 : * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2015/03/05 3.0 新建 *******************************************************************************/ BOOL CGGAData::DoGenerateVRS(int i_BSID, int i_cell , CPPPCellData *tempCellData , CVRSAtmos * tempVRS)
20.查看调用
/******************************************************************************* * 函数名称 : InitVrsToCode() * 函数描述 : 发送编码观测值 * 参数 : MsgToCode* v_msgtocode,CPPPFileData *tempData , CVRSAtmos *tempVrs * 返回值 : void * 备注 : * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2015/03/08 3.0 新建 * 2015/08/14 3.0 加入PCO修正基准站坐标 *******************************************************************************/ void CGGAData::InitVrsToCode( MsgToCode* v_msgtocode,CPPPFileData *tempData , CVRSAtmos *tempVrs)
21.查看调用
/******************************************************************************* * 函数名称 : ReInitLine() * 函数描述 : ReInit Baseline * 参数 : * 返回值 : void * 备注 : Intrinsic Function * 修改日期 修改人 修改内容 * ----------------------------------------------- * 2015/02/05 3.0 新建 *******************************************************************************/ void CLineInfo::ReInitLine()
22.何时被调用?
CGGAData::CGGAData( CVRSProcMgr* pVRSProcMgr ) :IGGAData(pVRSProcMgr) { hDllInst = LoadLibrary("CoEncode.dll"); m_Encode=(Encode)GetProcAddress(hDllInst,"Encode"); hDllHeight = LoadLibrary("GeoInter.dll"); m_IndexData=(IndexData)GetProcAddress(hDllHeight,"IndexData"); memset(StaPos_Old,,sizeof(StaPos_Old)); // v_sendchain.reserve(10); }
23.再谈
freopen( "CONOUT$","w",stdout);
freopen是被包含于C标准库头文件<stdio.h>中的一个函数,用于重定向输入输出流。该函数可以在不改变代码原貌的情况下改变输入输出环境,但使用时应当保证流是可靠的。
freopen(_In_z_ const char * _Filename, _In_z_ const char * _Mode, _Inout_ FILE * _File);
不用管前面的in_z,形参说明:
功能:把一个存在文件流指定到另一文件。
CONOUT$:意思是控制台输出
24.UnRegisterNotify函数
两个参数是脱离用户和已关联基站的关系,
一个参数是删除用户。
25.多用户带来的问题与困难是:每个用户都需要一个虚拟参考站,并且需要对虚拟参考站的数据进行编码发送给该用户。
26.神秘的CMSG
这个类出现的地方为:
/******************************************************************************* * 文件名称 : MsgSwitchMgr.h * 作 者 : 3.0 * 创建时间 : 2014/11/15 10:00 * 文件描述 : 消息通信管理类 * 版权声明 : Copyright (C) 2014-2015 * 修改历史 : 2014/11/15 1.00 初始版本 *******************************************************************************/ struct CMSG { int m_id; string m_strData; CMSG(int id, const char* sz) :m_id(id) ,m_strData(sz) { } ~CMSG() { } protected: CMSG(const CMSG& pObj); CMSG& operator=(const CMSG& pObj); };
队列:
TQueue<CMSG*> m_qMSG;
调用:
CMSG* pMsg = m_qMSG.Pop();
int CVRSProcMgr::PushData( int id, const char* szdata ) { CMSG* pMSG = new CMSG(id,szdata);}
其中,pop为返回链表中首元素的指针,并删除首元素。
27.关键点,GGA线程
typedef map<int, CGGAProc*> tGGAPROC; //多个gga线程,多个用户 tGGAPROC m_vecGGAProc;
28.解析szdata序列化字符串,赋值到jreadvalue中
(jReader.parse(szdata, jReadValue))
29.vector中erase和delete一起用:有一个很有用的例子
;i < index;i++) { vector <CPPPFileData*>::iterator it = v_ObsChainB.begin(); delete *it; v_ObsChainB.erase(it); } ;) { delete *it; it = v_ObsChainA.erase(it); } v_ObsChainA.clear();
这里面,两个删除后的动作不一样,一个是
v_ObsChainB.erase(it);另一个是
it = v_ObsChainA.erase(it);两处存在不同。 综合参考这两个链接:https://blog.csdn.net/duan19920101/article/details/50717748 https://www.cnblogs.com/young8848/p/4467472.html 30.程序中的错误:修复组网时判断的bug
] == temp_MatchA.i_Ref[] && temp_MatchA.i_Ref[] == temp_MatchC.i_Ref[]) )
修改为:
] == temp_MatchB.i_Ref[] && temp_MatchA.i_Ref[] == temp_MatchC.i_Ref[]) )
VRSProcess(二)的更多相关文章
- 【小程序分享篇 二 】web在线踢人小程序,维持用户只能在一个台电脑持登录状态
最近离职了, 突然记起来还一个小功能没做, 想想也挺简单,留下代码和思路给同事做个参考. 换工作心里挺忐忑, 对未来也充满了憧憬与担忧.(虽然已是老人, 换了N次工作了,但每次心里都和忐忑). 写写代 ...
- 前端开发中SEO的十二条总结
一. 合理使用title, description, keywords二. 合理使用h1 - h6, h1标签的权重很高, 注意使用频率三. 列表代码使用ul, 重要文字使用strong标签四. 图片 ...
- 【疯狂造轮子-iOS】JSON转Model系列之二
[疯狂造轮子-iOS]JSON转Model系列之二 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇<[疯狂造轮子-iOS]JSON转Model系列之一> ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- 谈谈一些有趣的CSS题目(十二)-- 你该知道的字体 font-family
开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节. 解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题 ...
- MIP改造常见问题二十问
在MIP推出后,我们收到了很多站长的疑问和顾虑.我们将所有疑问和顾虑归纳为以下二十个问题,希望对大家理解 MIP 有帮助. 1.MIP 化后对其他搜索引擎抓取收录以及 SEO 的影响如何? 答:在原页 ...
- 如何一步一步用DDD设计一个电商网站(二)—— 项目架构
阅读目录 前言 六边形架构 终于开始建项目了 DDD中的3个臭皮匠 CQRS(Command Query Responsibility Segregation) 结语 一.前言 上一篇我们讲了DDD的 ...
- ASP.NET Core 之 Identity 入门(二)
前言 在 上篇文章 中讲了关于 Identity 需要了解的单词以及相对应的几个知识点,并且知道了Identity处在整个登入流程中的位置,本篇主要是在 .NET 整个认证系统中比较重要的一个环节,就 ...
- MVVM模式和在WPF中的实现(二)数据绑定
MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...
随机推荐
- Node.js中Process.nextTick()和setImmediate()的区别
一.Webstrom使用node.js IDE的问题 在区别这两个函数之前来说一下Webstrom使用node.js IDE的问题,在配置Node.js的IDE了,但setImmediate().re ...
- 设置TableView section header的颜色
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInte ...
- Executor、ExecutorService、ThreadPoolExecutor
1.Executor Executor接口中中只有一个方法 执行已提交的Runnable任务对象. ExecutorService pool1 = Executors.newFixedThreadPo ...
- vue + element ui 表格自定义表头,提供线上demo
前言:工作中用到 vue+element ui 的前端框架,需要使用自定义表头,需要使用 re.转载请注明出处:https://www.cnblogs.com/yuxiaole/p/9710826.h ...
- Docker for Windows(二)登录与配置镜像加速器
一.启动Docker for Windows 通过桌面Docker Desktop启动,右下角出现的白色鲸鱼图标保持稳定时,表示Docker正在正常运行,将鼠标移到图标上会显示"Docker ...
- freecodecamp 基础算法题笔记
数组与字符串的转化 字符串转化成数组 reverse方法翻转数组顺序 数组转化成字符串. function reverseString(str) { a= str.split("" ...
- HTML meta标签总结,HTML5 head meta属性整理
原文链接:http://caibaojian.com/mobile-meta.html <!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 -- ...
- Asp.net MVC 移除不用的视图引擎
Asp.net MVC 默认提供两个视图引擎,分别为: WebFormViewEngine 和 RazorViewEngine.MVC在查找视图时,会按照指定的顺序进行查找.当我们的MVC程序未找到相 ...
- 【Python】Java程序员学习Python(七)— 文本类详解(字符串、str)
如果一个女孩子喜欢看龙猫,那么请珍惜她,呵护她 任何一门语言,字符串总是最基本也是最需要掌握的一个变量,想想入门的Hello World,输出的就是字符串. 官方文档:https://docs.pyt ...
- oracle的sequence出现gap的问题
转自 http://web4.blog.163.com/blog/static/189694131201132184850561/ 今天碰到一个问题,数据库表有一个字段的值是通过sequence来生成 ...