私はstd :: thread用のいくつかのクラスワーパを持っています。ここではコンストラクタは次のとおりです。std :: vector :: emplace_backの使用
template <typename Function, typename... Args>
InterruptibleThread(Function&& fun, Args&&... args)
{
_thread = std::thread([](std::atomic_bool * f, Function&& function, Args&&... arguments)
{
_flag_ref = f;
(function)(std::forward<Args>(arguments)...);
},
&_flag,
std::forward<Function>(fun)
, std::forward<Args>(args)...
);
}
そして私は(例)ので、それを使用しています: InterruptibleThread(& SourceImageList :: StartFrameProcessingStatic、この、のstd :: refの(それ))
コンパイラのビルドこのコードは成功しています。しかし、今、私はそのようなオブジェクトのベクトルを作りたいと思います:
std::vector<InterruptibleThread> grp;
私は私がやっているので、何をスタックに割り当てるしたいです:
grp.emplace_back(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it));
そして、私はこれを取得していますエラー:ここ
C2064 term does not evaluate to a function taking 0 arguments
は、コンパイラによって検証されているオプションは次のとおりです。
1) grp.push_back(new InterruptibleThread(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it)));
2) grp.push_back(InterruptibleThread(&SourceImageList::StartFrameProcessingStatic, this, std::ref(it)));
しかし、最初のものはヒープ上にオブジェクトを割り当てているので、手動で解放する必要があり、2番目のものはオブジェクトのコピーを作成する必要があります。
ここでemplace_back
(コンパイラはMSVC 2015アップデート3)を使用できますか?
更新
[OK]を、私は、回答に基づいて、いくつかの修正をしました。使用の
#pragma once
#include <exception>
#include <atomic>
#include <thread>
#include <future>
#include <windows.h>
// Synopsis
class InterruptThreadException;
class InterruptibleThread;
// Interrupt exception
class InterruptThreadException : public virtual std::exception {
public:
virtual char const* what() const override { return "interrupt"; }
}; // class InterruptThreadException
// Interruptible thread
class InterruptibleThread {
public:
static void InterruptionPoint() noexcept(false) {
if (!InterruptibleThread::_flag_ref) { return; }
if (!InterruptibleThread::_flag_ref->load()) { return; }
throw InterruptThreadException();
} // check_for_interrupt
template <typename Function>
InterruptibleThread(Function&& fun) :
_thread([this, fun = std::move(std::forward<Function>(fun))]
{
_flag_ref = _flag.get();
fun();
})
{}
InterruptibleThread(InterruptibleThread&&) = default;
InterruptibleThread(const InterruptibleThread&) = delete;
bool Interrupting() const { return _flag->load(); }
void Interrupt() { _flag->store(true); }
void Join()
{
_thread.join();
}
bool TimedJoin(int msec)
{
return (std::async([=]() {Join(); }).wait_for(std::chrono::milliseconds(msec)) != std::future_status::timeout);
}
bool Joinable()
{
return _thread.joinable();
}
void Terminate()
{
TerminateThread(_thread.native_handle(), -1);
}
~InterruptibleThread()
{
if (_flag.get() != nullptr)
{
*_flag = false;
Interrupt();
}
if (_thread.joinable())
_thread.join()
}
private:
static thread_local std::atomic_bool* _flag_ref;
std::unique_ptr<std::atomic_bool> _flag = std::make_unique<std::atomic_bool>();
std::thread _thread;
};
そして例:
std::vector<InterruptibleThread> grp;
for (auto it : _sourceImages)
grp.emplace_back([this, it] {
it->StartFrameProcessing();
it->SetImageDelay(const_cast<EngineConfig*>(GetConfig())->ImageDelay);
});
"私はここにemplace_back使用することはできますが、" - あなたは* *てみたのですか?実際にはあなたの質問に答えるだけです。 –
2番目の 'push_back'バージョンは、コピーを作成するのではなくベクトルにプッシュバックするときに、実際に' InterruptibleThread'を '移動 'する必要があります。コンパイラはほぼ確実にこのオーバーロードを使います。 – ArchbishopOfBanterbury
@ArchbishopOfBanterbury C++ 11では、 'push_back'にはrvalueのオーバーロードがあるので、コンパイラはそれを確実に移動します(つまり、コンパイラは追加の最適化を行いません)http://en.cppreference.com/w/cpp/container/ vector/push_back – vsoftco