Some Useful Tools Used in C++
Vcstool
- Vcstool is a Version Control System (VCS) tool.
- Designed to make working with multiple repositories easier.
- Vcstool supports Git, Mercurial, Subversion, Bazaar.
- https://github.com/dirk-thomas/vcstool.
- This tool should not be confused with vcstools.
vcstools
provides a Python API for interacting with different version control systems.
Installation
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver hkp://pool.sks-keyservers.net --recv-key 0xAB17C654
sudo apt-get update
sudo apt-get install python3-vcstool
or:
sudo pip install vcstool
Usage
Repositories File
- Using
YAML
format to encode the repositories. - Include a root key
repositories
. - Each of these dictionaries contains keys
type
,url
,version
.- If the
version
key is omitted thedefault branch
is being used.
- If the
Example:
repositories:
vcstool:
type: git
url: git@github.com:dirk-thomas/vcstool.git
version: master
old_tools/rosinstall:
type: svn
url: https://github.com/vcstools/rosinstall/trunk
version: 748
Import set of repositories
vcs import
command clones all repositories which are passed in viastdin
in YAML format.
vcs import < repositories.yaml
Export set of repositories
vcs export
command outputs thepath
,vcs type
,url
andversion
information for all repositories inYAML
format.
vcs export > repositories.yaml
Validate repositories file
vcs validate
command takes a YAML file which is passed in viastdin
and validates its contents and format.
vcs validate < repositories.yaml
pybind11
- https://github.com/pybind/pybind11.
- Tutorial Document.
pybind11
是一个轻量级的只包含一组头文件的C++库。- 主要用于创建已有C++代码的Python封装版本,实现C++和Python之间的无缝操作。
Mutex
- C++使用
锁
(Mutex,互斥量)提供共享数据的访问保护,用于多线程编程
。
无锁Demo
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <stdexcept>
int counter = 0;
void increase(int time) {
for (int i = 0; i < time; i++) {
// 当前线程休眠1毫秒,此处会发生多线程的竞争现象
std::this_thread::sleep_for(std::chrono::milliseconds(1));
counter++;
}
}
int main(int argc, char** argv) {
std::thread t1(increase, 10000);
std::thread t2(increase, 10000);
t1.join();
t2.join();
std::cout << "counter:" << counter << std::endl;
return 0;
}
Output:
counter:19997
Reason:
counter++
不是原子操作,而是由多条汇编指令完成。- 在读取
counter
当前值之后,两个进程分别对其进行操作,最终输出结果+1
,而期望结果是+2
。
std::mutex
- 访问之前加锁操作
lock()
。- 加锁不成功会导致进程阻塞。
- 访问之后要进行
释放锁
unlock()
,否则会导致死锁
。 try_lock()
:尝试上锁,上锁不成功,当前进程不阻塞。
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <stdexcept>
int counter = 0;
std::mutex mtx; // 保护counter
void increase(int time) {
for (int i = 0; i < time; i++) {
mtx.lock();
// 当前线程休眠1毫秒
std::this_thread::sleep_for(std::chrono::milliseconds(1));
counter++;
mtx.unlock();
}
}
int main(int argc, char** argv) {
std::thread t1(increase, 10000);
std::thread t2(increase, 10000);
t1.join();
t2.join();
std::cout << "counter:" << counter << std::endl;
return 0;
}
Output:
counter:20000
std::lock_guard
- 仅使用
std::mutex
会发生死锁
。 std::lock_guard
只有构造函数和析构函数:- 调用构造函数时,会自动调用传入的对象的
lock()
函数。 - 调用析构函数时,会自动调用
unlock()
函数。
- 调用构造函数时,会自动调用传入的对象的
- 搭配
std::mutex
和std::lock_guard
可以避免死锁
。
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <chrono>
#include <stdexcept>
int counter = 0;
std::mutex mtx; // 保护counter
void increase_proxy(int time, int id) {
for (int i = 0; i < time; i++) {
// std::lock_guard对象构造时,自动调用mtx.lock()进行上锁
// std::lock_guard对象析构时,自动调用mtx.unlock()释放锁
std::lock_guard<std::mutex> lk(mtx);
// 线程1上锁成功后,抛出异常:未释放锁
if (id == 1) {
throw std::runtime_error("throw excption....");
}
// 当前线程休眠1毫秒
std::this_thread::sleep_for(std::chrono::milliseconds(1));
counter++;
}
}
void increase(int time, int id) {
try {
increase_proxy(time, id);
}
catch (const std::exception& e){
std::cout << "id:" << id << ", " << e.what() << std::endl;
}
}
int main(int argc, char** argv) {
std::thread t1(increase, 10000, 1);
std::thread t2(increase, 10000, 2);
t1.join();
t2.join();
std::cout << "counter:" << counter << std::endl;
return 0;
}
Output:
id:1, throw excption....
counter:10000