Seperate enabling PBVH_BMESH from enabling DynTopo: * Created a new option to globally disabled DynTopo. * The DynTopo panel header now reads "Dynamic Mode", to hopefully signal that turning on PBVH_BMESH is a seperate step from enabling or disabling DynTopo itself. * The first checkbox in the panel is "DynTopo" so it should be clear enough (it's on by default, with multiple layers of file versioning checks). PBVH_BMesh's undo system: * CD_MESH_ID layers are now permanently saved once they are created (by default they are not). This fixed a *lot* of bugs: Before this the undo system had to save maps between mesh indices and mesh IDs on transitioning between sculpt and global undo steps. This was extremely error prone, and it simply wasn't possible to cover all of the corner cases * Note that there is still an odd bug where the first global undo push after a sculpt step gets ignored, I dunno what's up with this. * Dyntopo undo should be nearly (hopefully completely) bug-free after this commit. C++20 * Made a few small changes to get blender to compile with c++20. std::result_of was removed, had to replace a couple of usages of it with std::invoke_result. * I'm planning to do some design studies on rewriting sculpt into C++. * I strongly suspect we are going to need C++20'a new concepts feature if we move sculpt into C++. I'm planning to do some design studies on how that might work.
126 lines
3.0 KiB
C++
126 lines
3.0 KiB
C++
/*******************************************************************************
|
|
* Copyright 2015-2016 Juan Francisco Crespo Galán
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
******************************************************************************/
|
|
|
|
#pragma once
|
|
|
|
/**
|
|
* @file ThreadPool.h
|
|
* @ingroup util
|
|
* The ThreadPool class.
|
|
*/
|
|
|
|
#include "Audaspace.h"
|
|
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <vector>
|
|
#include <thread>
|
|
#include <queue>
|
|
#include <future>
|
|
#include <functional>
|
|
|
|
AUD_NAMESPACE_BEGIN
|
|
/**
|
|
* This represents pool of threads.
|
|
*/
|
|
class AUD_API ThreadPool
|
|
{
|
|
private:
|
|
/**
|
|
* A queue of tasks.
|
|
*/
|
|
std::queue<std::function<void()>> m_queue;
|
|
|
|
/**
|
|
* A vector of thread objects.
|
|
*/
|
|
std::vector<std::thread> m_threads;
|
|
|
|
/**
|
|
* A mutex for synchronization.
|
|
*/
|
|
std::mutex m_mutex;
|
|
|
|
/**
|
|
* A condition variable used to stop the threads when there are no tasks.
|
|
*/
|
|
std::condition_variable m_condition;
|
|
|
|
/**
|
|
* Stop flag.
|
|
*/
|
|
bool m_stopFlag;
|
|
|
|
/**
|
|
* The number fo threads.
|
|
*/
|
|
unsigned int m_numThreads;
|
|
|
|
// delete copy constructor and operator=
|
|
ThreadPool(const ThreadPool&) = delete;
|
|
ThreadPool& operator=(const ThreadPool&) = delete;
|
|
public:
|
|
/**
|
|
* Creates a new ThreadPool object.
|
|
* \param count The number of threads of the pool. It must not be 0.
|
|
*/
|
|
ThreadPool(unsigned int count);
|
|
|
|
virtual ~ThreadPool();
|
|
|
|
/**
|
|
* Enqueues a new task for the threads to realize.
|
|
* \param t A function that realices a task.
|
|
* \param args The arguments of the task.
|
|
* \return A future of the same type as the return type of the task.
|
|
*/
|
|
#if __cplusplus > 201703L
|
|
template<class T, class... Args>
|
|
std::future<typename std::invoke_result<T, Args...>::type> enqueue(T&& t, Args&&... args)
|
|
{
|
|
using pkgdTask = std::packaged_task<typename std::invoke_result<T, Args...>::type()>;
|
|
#else
|
|
template<class T, class... Args>
|
|
std::future<typename std::result_of<T(Args...)>::type> enqueue(T&& t, Args&&... args)
|
|
{
|
|
using pkgdTask = std::packaged_task<typename std::result_of<T(Args...)>::type()>;
|
|
#endif
|
|
std::shared_ptr<pkgdTask> task = std::make_shared<pkgdTask>(std::bind(std::forward<T>(t), std::forward<Args>(args)...));
|
|
auto result = task->get_future();
|
|
|
|
m_mutex.lock();
|
|
m_queue.emplace([task]() { (*task)(); });
|
|
m_mutex.unlock();
|
|
|
|
m_condition.notify_one();
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Retrieves the number of threads of the pool.
|
|
* \return The number of threads.
|
|
*/
|
|
unsigned int getNumOfThreads();
|
|
|
|
private:
|
|
|
|
/**
|
|
* Worker thread function.
|
|
*/
|
|
void threadFunction();
|
|
};
|
|
AUD_NAMESPACE_END
|