Boost学习笔记
1 system_time
头文件:
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
获取系统时间:
// 注意要用unsigned int格式
unsigned int t = boost::get_system_time().time_of_day().total_milliseconds();
延时:
// 主线程延时
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(3));
// 子线程延时
boost::this_thread::sleep(boost::get_system_time() + boost::posix_time::seconds(3));
获取时
、分
、秒
、毫秒
:
const boost::posix_time::ptime now = boost::posix_time::microsec_clock::local_time();
const boost::posix_time::time_duration td = now.time_of_day();
int hh = td.hours();
int mm = td.minutes();
int ss = td.seconds();
int ms = td.total_milliseconds() - ((hh * 3600 + mm * 60 + ss) * 1000)
获取年
、月
、日
并装换为字符串:
#include <boost/date_time/gregorian/gregorian.hpp>
std::string data = boost::gregorian::to_iso_string(boost::gregorian::day_clock::local_day());
2 多线程
2.1 互斥体
2.1.1 mutex+scoped_lock
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
//锁住范围内的某一段代码,只被一个线程访问,其它线程被阻塞,
//退出该范围时,锁会被(析构函数)自动销毁
boost::mutex io_mutex;
void fun(int id)
{
//std::cout << "init" << std::endl;
boost::mutex::scoped_lock lock(io_mutex);
//if (lock.owns_lock())
// std::cout << "sucess" << std::endl;
//else
// std::cout << "faile" << std::endl;
for (int i = 0; i < 5; ++i)
{
std::cout << id << ": " << i << std::endl;
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));//延时,便于观察
}
}
int main()
{
boost::thread t1(fun, 1);
boost::thread t2(fun, 2);
t1.join();
t2.join();
}
2.1.2 try_mutex+scoped_try_lock
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
//尝试给某一段代码上锁,如果被某个线程锁住,其它线程会上锁失败,但
//会继续执行,也就是非阻塞
boost::try_mutex iomutex;
void fun(int id)
{
boost::try_mutex::scoped_try_lock lock(iomutex);//锁定mutex
if (lock.owns_lock())
{
//std::cout << "suceess" << std::endl;
for (int i = 0; i < 5; ++i)
{
std::cout << id << ": " << i << std::endl;
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
}
}
else
{
//std::cout << "faile" << std::endl;
boost::thread::yield(); //释放控制权
}
}
int main()
{
boost::thread t1(fun, 1);
boost::thread t2(fun, 2);
t1.join();
t2.join();
}
2.1.3 timed_mutex+scoped_timed_mutex
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
//给某一段代码上锁,并设置上锁的时间;
//在上锁时间内,只有线程A访问那一段代码,其它线程阻塞;
//超过上锁时间,若线程A还在访问,则其它线程就不再等待,继续往后执行;
//超过上锁时间,若线程A已经结束访问,则其它线程再对他上锁访问;
boost::timed_mutex iomutex;
void fun(int id)
{
boost::xtime xt;
boost::xtime_get(&xt,boost::TIME_UTC_);
xt.sec += 6; //设定的时间,这里单位为秒
boost::timed_mutex::scoped_timed_lock lock(iomutex, xt); //锁定mutex
if (lock.owns_lock())
{
std::cout << id << ":" << "Get lock." << std::endl;
for (int i = 0; i < 5; ++i)
{
std::cout << id << ": " << i << std::endl;
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
}
}
else
{
std::cout << id << ":" << "Not get lock." << std::endl;
boost::thread::yield(); //释放控制权
}
}
int main()
{
boost::thread t1(fun, 1);
boost::thread t2(fun, 2);
t1.join();
t2.join();
}
2.1.4 shared_mutex
#include <iostream>
#include <boost/thread.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/shared_mutex.hpp>
//下面实现的是读写锁,“写独占,读共享”,写的时候一个线程占用,其它线程阻塞,读的时候所有线程一起读;
//下的main函数中还有线程池的应用,名:thread_group;
//写加锁有两种实现方式:
// 1)shr_mutex.lock();
// shr_mutex.unlock();
// 2)boost::unique_lock<boost::shared_mutex> m(shr_mutex); //销毁时自动解锁
//读加锁有两种实现方式:
// 1)shr_mutex.lock_shared();
// shr_mutex.unlock_shared();
// 2)boost::shared_lock<boost::shared_mutex> m(shr_mutex); //销毁时自动解锁
boost::shared_mutex shr_mutex;
void write_process(int id) {
//shr_mutex.lock();
boost::unique_lock<boost::shared_mutex> m(shr_mutex);
for (int i = 0; i < 3; i++)
{
std::cout << id << ":" << i << std::endl;
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
}
//shr_mutex.unlock();
}
void read_process(int id) {
boost::shared_lock<boost::shared_mutex> m(shr_mutex);
//shr_mutex.lock_shared();
for (int i = 0; i < 3; i++)
{
std::cout << id << ":" << i << std::endl;
boost::thread::sleep(boost::get_system_time() + boost::posix_time::seconds(1));
}
//shr_mutex.unlock_shared();
}
int main() {
boost::thread_group threads;
for (int i = 0; i < 2; ++ i) {
//创建两个线程用于“写”
threads.create_thread(boost::bind(write_process, i));
//创建两个线程用于“读”
//threads.create_thread(boost::bind(read_process, i));
}
threads.join_all();
system("pause");
return 0;
}
2.2 条件变量
boost::condition的定义如下:
namespace boost
{
class condition : private boost::noncopyable // Exposition only.
// Class condition meets the NonCopyable requirement.
{
public:
condition();
~condition();
void notify_one();
// 唤起等待队列中的一个线程
void notify_all();
// 唤起等待队列中的所有线程
template <typename Lock> void wait(Lock& lock);
// ScopedLock 是一个lock对象,符合ScopedLock 概念
// 释放lock中mutex上的锁,阻塞该线程,直到任何人调用了this->notify_one()或
// this->notify_all(),然后重新lock mutex。
template <typename Lock, typename Predicate>
void void wait(Lock& lock, Predicate pred);
// ScopedLock 是一个lock对象,符合ScopedLock 概念
// 相当于while (!pred()) wait(lock)。
template <typename Lock>
bool timed_wait(Lock& lock, const xtime& xt);
// wait(Lock& lock)的限时版,当XT到达时,函数返回false,当因notify而返回时
// 函数返回true
template <typename Lock, typename Predicate>
bool timed_wait(Lock& lock, const xtime& XT, Predicate pred);
// wait(Lock& lock, Predicate pred)的限时版,当XT到达时,函数返回false,当
// 因notify和pred而而返回时函数返回true
};
};
如果定义了boost::condition cond,那么就可以用cond.wait(abc)语句让abc线程挂起,然后在另一个地方用cond.notify_one()语句把abc线程唤起,
2.3 智能指针
当多个线程同时访问某一段代码时,假如在这段代码中有指针变量*a
,那么每个线程里面会有自己的“*a
”变量,但变量所指向的地址是同一个,如果每个线程都执行*a
++,那么最后*a
的值是所有线程加的总和;如果要让每个线程的*a
是私有的,就需要用到智能指针;
#include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/tss.hpp>
#include <iostream>
boost::mutex io_mutex;
boost::thread_specific_ptr<int> ptr;//创建int型的智能指针
struct count
{
count(int id) : id(id) { }
void operator()()
{
if (ptr.get() == 0)//如果指针为空就申请空间
ptr.reset(new int(0));
for (int i = 0; i < 10; ++i)
{
(*ptr)++;
boost::mutex::scoped_lock lock(io_mutex);
std::cout << id << ": " << *ptr << std::endl;
}
}
int id;
};
int main()
{
boost::thread thrd1(count(1));
boost::thread thrd2(count(2));
thrd1.join();
thrd2.join();
system("pause");
return 0;
}
2.4 线程只运行一次
boost::call_once一般用与程序的初始化,对应的程序只被线程用一次;
#include <boost/thread/once.hpp>
int i = 0;
boost::once_flag flag = BOOST_ONCE_INIT;
void init()
{
++i;
}
void thread()
{
boost::call_once(&init, flag);
}
int main(int argc, char* argv[])
{
boost::thread thrd1(&thread);
boost::thread thrd2(&thread);
thrd1.join();
thrd2.join();
std::cout << i << std::endl;
system("pause");
return 0;
}
2.5 限制线程的个数
.h
#define THREAD_NUM_ADD 0
#define THREAD_NUM_DEL 1
class Mode
{
public:
Mode();
~Mode();
int m_thread_num_max = 4; // 控制的最大线程数目
void predict();
private:
int m_threads_num = 0;
boost::shared_mutex shr_mutex;
boost::thread_group threads_predict;
boost::thread_group threads_write;
void do_predict();
void write_process(int i);
};
.cpp
#include "trmode.h"
Mode::Mode()
{
}
Mode::~Mode()
{
threads_predict.join_all();
threads_write.join_all();
}
void Mode::predict()
{
//boost::function0<void> f = boost::bind(&Mode::do_predict, this);
//boost::thread t(f);
while (m_threads_num > m_thread_num_max); // 如果线程数目超过允许的最大数目就停留在这里
// 线程数目加1
threads_write.create_thread(boost::bind(&Mode::write_process, this, THREAD_NUM_ADD));
// 创建线程
threads_predict.create_thread(boost::bind(&Mode::do_predict, this));
}
void Mode::do_predict(TestDataInfo testdatainfo)
{
// do something...
boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(200));//延时,便于观察
// 线程数目减1
threads_write.create_thread(boost::bind(&Mode::write_process, this, THREAD_NUM_DEL));
}
void Mode::write_process(int i)
{
boost::unique_lock<boost::shared_mutex> m(shr_mutex);
if (i == THREAD_NUM_ADD)
m_threads_num ++;
else if (i == THREAD_NUM_DEL)
m_threads_num --;
}
main.cpp
#include <trmode.h>
int main()
{
Mode mode;
for (int i = 0; i<200; i++) {
mode.predict();
boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(10));//延时,便于观察
}
}
3 文件操作
需要包含的头文件:#include <boost/filesystem.hpp>
需要包含的静态库:libboost_filesystem.a
3.1 创建 path 变量
boost::filesystem::path p1("D:\\dir"); //windows下既可使用斜杠也可使用反斜杠(资源管理器地址栏中使用的就是反斜杠),又因为在c++中反斜杠是转义字符的标志,所以使用反斜杠的话还得再加一个反斜杠
boost::filesystem::path p2("D:/dir/data.dat"); //windows下推荐使用正斜杠
boost::filesystem::path p3("/user/dir"); //linux下使用正斜杠
boost::filesystem::path p4 = "./dir"; //path的构造函数没有声明为explicit,字符串可以隐式转换为path对象
p1 /= "child"; //path重载了 /=,其功能与成员append()相同。
if (p1 == p2); //支持比较操作
auto iter = p1.begin(); //支持迭代器来迭代其中的字符串
3.2 创建、删除、复制文件夹
boost::filesystem::create_directory(p1); //创建一级目录
boost::filesystem::create_directories(p1); //创建多级目录
boost::filesystem::remove(p1); //删除文件或空目录
boost::filesystem::remove_all(p1); //删除目录
boost::filesystem::copy_file(p1, p2); //拷贝
3.3 遍历文件夹
// 方法1
void recursive_dir(const boost::filesystem::path& dir)
{
//使用directory_iterator递归遍历目录
boost::filesystem::directory_iterator end; //空的directory_iterator构造函数生成一个指向end的迭代器
boost::filesystem::directory_iterator pos(dir); //传入一个path对象后可以使用++开始迭代操作
for (; pos != end; pos++)
{
if (boost::filesystem::is_directory(*pos))
recursive_dir(*pos); //directory_iterator迭代器返回的类型其实不是path,但它定义了一个到path的类型转换函数,因此这里是隐式转换
else
cout << *pos << endl; //输出文件名
}
}
// 方法2,支持深度遍历
boost::filesystem::recursive_directory_iterator end;
boost::filesystem::recursive_directory_iterator pos(p1);
for (; pos != end; pos++)
{
std::cout << pos.level() << std::endl; //获得当前目录深度
std::cout << *pos << std::endl; //输出文件名
}
// 方法2的指针模式
boost::filesystem::recursive_directory_iterator * end;
boost::filesystem::recursive_directory_iterator * pos;
end = new boost::filesystem::recursive_directory_iterator();
pos = new boost::filesystem::recursive_directory_iterator(p1);
for (; *pos != *end; (*pos)++)
{
std::cout << **pos << std::endl; //输出文件名
boost::filesystem::path p = **m_pos;
if (p.extension().string() == ".jpg" ) { // 判断该文件是否是jpg格式的
}
}
3.4 判断
boost::filesystem::exists(p1); //是否存在
boost::filesystem::is_directory(p1); //是否是目录
boost::filesystem::is_regular_file(p1); //是否是普通文件
boost::filesystem::is_empty(p1); //目录是否为空或文件大小是否为0
boost::filesystem::is_symlink(p1); //是否为链接文件
boost::filesystem::is_other(p1); //当文件存在且不是普通文件、目录或链接文件时返回true,其它文件类型可以通过文件状态类file_status获得
std::string strDir = p1.string(); //获取字符串(构造函数中传入的字符串为相对路径的话这里也是相对路径)
bool bRes = boost::filesystem::portable_posix_name(strDir); //判断是否符合posix文件命名规范
boost::filesystem::windows_name(strDir); //判断是否符合windows文件命名规范
boost::filesystem::portable_name(strDir); //相当于portable_posix_name() && windows_name
boost::filesystem::native(strDir); //在windows下相当于windows_name,其它操作系统下只是简单的判断文件名不是空格且不含斜杠
p1.is_complete(); //是否是一个完整的绝对路径
- 路径
boost::filesystem::current_path(); //获得当前路径
boost::filesystem::path parentPath = p3.parent_path(); //获得父路径
boost::filesystem::path parentPath = p3.system_complete(); //获得全路径(绝对路径)
boost::filesystem::initial_path(); //获得进入main函数时的当前路径
p1.relative_path(); //获得path的相对路径
p1.root_path(); //根路径: "C:/"
p1.root_name(); //根名字:"C:"
p1.root_directory(); //根目录: "/"
3.5 文件名
std::string name = p2.filename().string(); //文件名: data.dat
std::string s = p2.stem().string(); //不含扩展名的文件名: data
std::string extName = p2.extension().string(); //扩展名: .dat
boost::filesystem::rename(p1, p2); //改名
3.6 异常处理
// filesystem使用异常来处理文件操作时发生的错误,所以使用的时候应该加上异常处理
try
{
boost::filesystem::file_size(p1); //获得文件大小,文件不存在则会抛出异常
}
catch (boost::filesystem::filesystem_error& e)
{
cout << e.path1() << endl;
cout << e.what() << endl;
}
3.7 其他
p1.remove_filename(); //删除当前路径中最后的文件名
p1.replace_extension("hxx"); //改变文件扩展名
boost::filesystem::last_write_time(p1); //获得文件最后修改时间
boost::filesystem::space(p1); //获得路径下磁盘空间分配情况
boost::filesystem::file_size(p1); //获取文件大小,单位字节
4 分割字符串
//#include <boost/algorithm/string.hpp>
std::string line = "sdf sfd dfsfd sdf";
std::vector<std::string> line_split;
boost::split(line_split, line, boost::is_any_of(" "), boost::token_compress_on);
for (std::vector<std::string>::iterator it = line_split.begin();
it != line_split.end(); it++) {
std::string a = *it;
std::cout << a << std::endl;
}
5 字符串格式化format
将数字和字符串拼接在一起:
//#include <boost/format.hpp>
boost::format fmt("%s/aaa/%06d.png");
std::string s = (fmt % "xxx" % 123).str();
// s == "xxx/aaa/000123.png"