summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri van Heesch <doxygen@gmail.com>2020-08-05 20:11:31 (GMT)
committerDimitri van Heesch <doxygen@gmail.com>2020-08-05 20:11:31 (GMT)
commit45431b45fa0591a6de6b47c3fe9ff8dd0032aa4e (patch)
tree3144a00c2f4b8d50fd4321c9f1b7475090fe9f0c
parenta501c61d6424b6a17fdaf2991df7c3a80f2ddf09 (diff)
downloadDoxygen-45431b45fa0591a6de6b47c3fe9ff8dd0032aa4e.zip
Doxygen-45431b45fa0591a6de6b47c3fe9ff8dd0032aa4e.tar.gz
Doxygen-45431b45fa0591a6de6b47c3fe9ff8dd0032aa4e.tar.bz2
Implemented workaround for Visual Studio bug in std::packaged_task
-rw-r--r--src/doxygen.cpp10
-rw-r--r--src/threadpool.h17
2 files changed, 19 insertions, 8 deletions
diff --git a/src/doxygen.cpp b/src/doxygen.cpp
index 0ee908a..776caca 100644
--- a/src/doxygen.cpp
+++ b/src/doxygen.cpp
@@ -9143,8 +9143,9 @@ static void parseFilesMultiThreading(const std::shared_ptr<Entry> &root)
numThreads = std::thread::hardware_concurrency();
}
msg("Processing input using %lu threads.\n",numThreads);
- ThreadPool threadPool(numThreads);
- std::vector< std::future< std::vector< std::shared_ptr<Entry> > > > results;
+ using FutureType = std::vector< std::shared_ptr<Entry> >;
+ ThreadPool<FutureType> threadPool(numThreads);
+ std::vector< std::future< FutureType > > results;
for (const auto &s : g_inputFiles)
{
bool ambig;
@@ -9237,8 +9238,9 @@ static void parseFilesMultiThreading(const std::shared_ptr<Entry> &root)
{
std::size_t numThreads = std::thread::hardware_concurrency();
msg("Processing input using %lu threads.\n",numThreads);
- ThreadPool threadPool(numThreads);
- std::vector< std::future< std::shared_ptr<Entry> > > results;
+ using FutureType = std::shared_ptr<Entry>;
+ ThreadPool< FutureType > threadPool(numThreads);
+ std::vector< std::future< FutureType > > results;
for (const auto &s : g_inputFiles)
{
// lambda representing the work to executed by a thread
diff --git a/src/threadpool.h b/src/threadpool.h
index 5b3f823..42c36ed 100644
--- a/src/threadpool.h
+++ b/src/threadpool.h
@@ -29,6 +29,13 @@
/// Class managing a pool of worker threads.
/// Work can be queued by passing a function to queue(). When the
/// work is done the result of the function will be passed back via a future.
+///
+/// Note that due to a bug in Visual Studio's std::packaged_task implementation
+/// it does not allow m_work to have a void() template parameter, and still assign
+/// R() to it (you will get C2280: "attempting to reference a deleted function error").
+/// So to work around this we pass the return type with the class itself :-(
+/// See also https://stackoverflow.com/q/26733430/784672
+template<class R>
class ThreadPool
{
public:
@@ -54,7 +61,9 @@ class ThreadPool
/// Queue the lambda 'task' for the threads to execute.
/// A future of the return type of the lambda is returned to capture the result.
- template<class F, class R=std::result_of_t<F&()> >
+ /// use this once the Visual Studio bug is fixed:
+ /// template<class F, class R=std::result_of_t<F&()> >
+ template<class F>
std::future<R> queue(F&& f)
{
// wrap the function object into a packaged task, splitting
@@ -98,7 +107,7 @@ class ThreadPool
while(true)
{
// pop a task off the queue:
- std::packaged_task<void()> f;
+ std::packaged_task<R()> f;
{
// usual thread-safe queue code:
std::unique_lock<std::mutex> l(m_mutex);
@@ -121,8 +130,8 @@ class ThreadPool
std::mutex m_mutex;
std::condition_variable m_cond;
- // note that a packaged_task<void> can store a packaged_task<R>:
- std::deque< std::packaged_task<void()> > m_work;
+ // note that a packaged_task<void()> can store a packaged_task<R()> (but not with buggy Visual Studio)
+ std::deque< std::packaged_task<R()> > m_work;
// this holds futures representing the worker threads being done:
std::vector< std::future<void> > m_finished;