我的代码有一个数据结构,例如"字符串的vecor矢量。我有2个主题:
THRE 1正在向此数据结构(RAM中的缓冲区)写入数据。
并行运行的线程2应该将数据从上面的缓冲区复制,即数据结构到每个" x"毫秒。
我想知道如何在C ++中实现这一目标?它应该考虑关键 问题陈述中的要点如下:
a)从缓冲区到文件的副本只能在" X" 毫秒。
b)两个线程之间的同步。
根据问题更详细地编辑查询
我想构建一个库(* .lib)&这个库公开了一些API,因此它从EXE或通过这些API使用我的库的任何实体获取输入数据。 假设我的库收到的数据是字符串向量的形式。
FillLibraryDataStructure(std::vector<std::string>); // is the API of this library. Any app can call this API & pass a vector of string to this library.
Example app code:
for(int i=100; i<100;i))
{
std::vector<std::string> vec = GetVectorOfString(); // GetVectorOfString from business logic
FillLibraryDataStructure(vec);
}
图书馆代码拥有共享资源:
// Within library I've a 2D vector i.e. vector of vector of strings where all the vector of strings passed by application to this librray are added as a new row in vecofvecofstr.
共享资源:
std::vector<std::vector<string>> vecofvecofstr;
THREAD 1:将从API接收的数据复制到数据结构,即字符串向量的向量。
vecofvecofstr.push_back(vec);
THREAD 2:将此向量的字符串(在第一个线程中写入)的内容复制到文件(XML,HTML等)。 对于每一个&#34; X&#34; miiliseconds
关于thread1的更多要点:1)线程1应该正在运行 连续地,即当应用程序调用API数据时 收到的应该放到数据结构vecofvecofstr。 2)之后 &#34; X&#34;将数据复制到缓冲区的二恶习,第二个线程应该 开始&amp;它应该复制所有转储到缓冲区的东西 直到约会。再次&#34; X&#34; milisonds线程2应暂停&amp;等待 为&#34; X&#34;毫秒。
我如何实现这一目标。这里第一个线程是我的库代码将在其中运行的默认线程。 我如何使用C ++实现这一目标?
答案 0 :(得分:0)
作为对一般问题的一般回答,有两种可能的选择:
1-使用一些等待,信号命令来休眠和并行唤醒线程
2-使用一些睡眠来提供读取线程
的X毫秒如果您需要更好的答案,请提供更多详情
答案 1 :(得分:0)
您可以使用std::mutex
和std::condition_variable>
。并且双缓冲区可以将锁定保持在最低限度。
std::condition_variable>
是与std必须提供的事件最接近的事情,它的使用有点人为,但它有效。
下面的示例使用双缓冲区,因此您可以在线程2保存到文件时继续缓冲数据,而无需锁定。
使用std:condition_variable,因此您的应用程序可以在不等待的情况下退出。只有在您希望应用程序立即退出时才需要这样做,否则您可以使用计时器。对notify_all()
的调用将阻止wait_for()超时,并立即唤醒写入线程,因此它可以退出而无需等待超时发生。请参阅参考:http://en.cppreference.com/w/cpp/thread/condition_variable
部首:
#include <mutex>
// a generic double buffer
template<typename _Data>
class DoubleBuffer
{
private:
std::mutex mutex_;
std::vector<std::vector<_Data>> storeBuffer_;
std::vector<std::vector<_Data>> saveBuffer_;
public:
void lock() { mutex_.lock(); }
void unlock() { mutex_.unlock();}
auto& GetStoreBuffer() { return storeBuffer_; }
auto& GetSaveBuffer() { return saveBuffer_; }
auto& Swap()
{
std::lock_guard<std::mutex> lock(mutex_);
std::swap(storeBuffer_, saveBuffer_);
}
};
在你的图书馆:
#include <condition_variable>
#include <thread>
#include <chrono>
#include <mutex>
#include <vector>
#include <string>
// As an example, could be inside a class, or struct
static std::condition_variable exiting;
static std::mutex lk_exiting;
static DoubleBuffer<std::string> yourBuffer;
void FillLibraryDataStructure(std::vector<std::string> strings)
{
// the lock is only for the duration of a swap - very short at worst.
std::lock_guard<DoubleBuffer<std::string>> lock(yourBuffer);
yourBuffer.GetStoreBuffer().emplace_back(strings);
}
void StoreLoop()
{
for(;;)
{
{ // wait_for() unlocks lk_exiting, doc says lock should
// be set before cv is triggered.
std::unique_lock<std::mutex> lk_exiting;
if (std::cv_status::no_timeout == exiting.wait_for(lk_exiting, 60s))
break; // app is exiting
}
yourBuffer.Swap();
auto& stringsToSave = GetSaveBuffer();
// save... You do have plenty of time.
}
}
// as an example. A destructor would be a good place for this
void Exit_Application()
{
// stops the wait_for operation in StoreLoop()
exiting.notify_all();
}