Vcstool

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 the default branch is being used.

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 via stdin in YAML format.
vcs import < repositories.yaml

Export set of repositories

  • vcs export command outputs the path, vcs type, url and version information for all repositories in YAML format.
vcs export > repositories.yaml

Validate repositories file

  • vcs validate command takes a YAML file which is passed in via stdin and validates its contents and format.
vcs validate < repositories.yaml

pybind11

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::mutexstd::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