/*========================================================================= Program: Visualization Toolkit Module: vtkMultiThreader.h Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen All rights reserved. See Copyright.txt or http://www.kitware.com/Copyright.htm for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ /** * @class vtkMultiThreader * @brief A class for performing multithreaded execution * * vtkMultithreader is a class that provides support for multithreaded * execution using pthreads on POSIX systems, or Win32 threads on * Windows. This class can be used to execute a single * method on multiple threads, or to specify a method per thread. */ #ifndef vtkMultiThreader_h #define vtkMultiThreader_h #include "vtkCommonCoreModule.h" // For export macro #include "vtkObject.h" #include // For std::mutex #if defined(VTK_USE_PTHREADS) #include // Needed for PTHREAD implementation of mutex #include // Needed for unix implementation of pthreads #include // Needed for unix implementation of pthreads #endif // If VTK_USE_PTHREADS is defined, then pthread_create() will be // used to create multiple threads // Defined in vtkSystemIncludes.h: // VTK_MAX_THREADS // If VTK_USE_PTHREADS is defined, then the multithreaded // function is of type void *, and returns nullptr // Otherwise the type is void which is correct for WIN32 // Defined in vtkSystemIncludes.h: // VTK_THREAD_RETURN_VALUE // VTK_THREAD_RETURN_TYPE #ifdef VTK_USE_PTHREADS typedef void* (*vtkThreadFunctionType)(void*); typedef pthread_t vtkThreadProcessIDType; // #define VTK_THREAD_RETURN_VALUE nullptr // #define VTK_THREAD_RETURN_TYPE void * typedef pthread_t vtkMultiThreaderIDType; #endif #ifdef VTK_USE_WIN32_THREADS typedef vtkWindowsLPTHREAD_START_ROUTINE vtkThreadFunctionType; typedef vtkWindowsHANDLE vtkThreadProcessIDType; // #define VTK_THREAD_RETURN_VALUE 0 // #define VTK_THREAD_RETURN_TYPE DWORD __stdcall typedef vtkWindowsDWORD vtkMultiThreaderIDType; #endif #if !defined(VTK_USE_PTHREADS) && !defined(VTK_USE_WIN32_THREADS) typedef void (*vtkThreadFunctionType)(void*); typedef int vtkThreadProcessIDType; // #define VTK_THREAD_RETURN_VALUE // #define VTK_THREAD_RETURN_TYPE void typedef int vtkMultiThreaderIDType; #endif class VTKCOMMONCORE_EXPORT vtkMultiThreader : public vtkObject { public: static vtkMultiThreader* New(); vtkTypeMacro(vtkMultiThreader, vtkObject); void PrintSelf(ostream& os, vtkIndent indent) override; /** * This is the structure that is passed to the thread that is * created from the SingleMethodExecute, MultipleMethodExecute or * the SpawnThread method. It is passed in as a void *, and it is * up to the method to cast correctly and extract the information. * The ThreadID is a number between 0 and NumberOfThreads-1 that indicates * the id of this thread. The NumberOfThreads is this->NumberOfThreads for * threads created from SingleMethodExecute or MultipleMethodExecute, * and it is 1 for threads created from SpawnThread. * The UserData is the (void *)arg passed into the SetSingleMethod, * SetMultipleMethod, or SpawnThread method. */ class ThreadInfo { public: int ThreadID; int NumberOfThreads; int* ActiveFlag; std::mutex* ActiveFlagLock; void* UserData; }; //@{ /** * Get/Set the number of threads to create. It will be clamped to the range * 1 - VTK_MAX_THREADS, so the caller of this method should check that the * requested number of threads was accepted. */ vtkSetClampMacro(NumberOfThreads, int, 1, VTK_MAX_THREADS); virtual int GetNumberOfThreads(); //@} //@{ /** * Set/Get the maximum number of threads to use when multithreading. * This limits and overrides any other settings for multithreading. * A value of zero indicates no limit. */ static void SetGlobalMaximumNumberOfThreads(int val); static int GetGlobalMaximumNumberOfThreads(); //@} //@{ /** * Set/Get the value which is used to initialize the NumberOfThreads * in the constructor. Initially this default is set to the number of * processors or VTK_MAX_THREADS (which ever is less). */ static void SetGlobalDefaultNumberOfThreads(int val); static int GetGlobalDefaultNumberOfThreads(); //@} // These methods are excluded from wrapping 1) because the // wrapper gives up on them and 2) because they really shouldn't be // called from a script anyway. /** * Execute the SingleMethod (as define by SetSingleMethod) using * this->NumberOfThreads threads. */ void SingleMethodExecute(); /** * Execute the MultipleMethods (as define by calling SetMultipleMethod * for each of the required this->NumberOfThreads methods) using * this->NumberOfThreads threads. */ void MultipleMethodExecute(); /** * Set the SingleMethod to f() and the UserData field of the * ThreadInfo that is passed to it will be data. * This method (and all the methods passed to SetMultipleMethod) * must be of type vtkThreadFunctionType and must take a single argument of * type void *. */ void SetSingleMethod(vtkThreadFunctionType, void* data); /** * Set the MultipleMethod at the given index to f() and the UserData * field of the ThreadInfo that is passed to it will be data. */ void SetMultipleMethod(int index, vtkThreadFunctionType, void* data); /** * Create a new thread for the given function. Return a thread id * which is a number between 0 and VTK_MAX_THREADS - 1. This id should * be used to kill the thread at a later time. */ int SpawnThread(vtkThreadFunctionType, void* data); /** * Terminate the thread that was created with a SpawnThreadExecute() */ void TerminateThread(int thread_id); /** * Determine if a thread is still active */ vtkTypeBool IsThreadActive(int threadID); /** * Get the thread identifier of the calling thread. */ static vtkMultiThreaderIDType GetCurrentThreadID(); /** * Check whether two thread identifiers refer to the same thread. */ static vtkTypeBool ThreadsEqual(vtkMultiThreaderIDType t1, vtkMultiThreaderIDType t2); protected: vtkMultiThreader(); ~vtkMultiThreader() override; // The number of threads to use int NumberOfThreads; // An array of thread info containing a thread id // (0, 1, 2, .. VTK_MAX_THREADS-1), the thread count, and a pointer // to void so that user data can be passed to each thread ThreadInfo ThreadInfoArray[VTK_MAX_THREADS]; // The methods vtkThreadFunctionType SingleMethod; vtkThreadFunctionType MultipleMethod[VTK_MAX_THREADS]; // Storage of MutexFunctions and ints used to control spawned // threads and the spawned thread ids int SpawnedThreadActiveFlag[VTK_MAX_THREADS]; std::mutex* SpawnedThreadActiveFlagLock[VTK_MAX_THREADS]; vtkThreadProcessIDType SpawnedThreadProcessID[VTK_MAX_THREADS]; ThreadInfo SpawnedThreadInfoArray[VTK_MAX_THREADS]; // Internal storage of the data void* SingleData; void* MultipleData[VTK_MAX_THREADS]; private: vtkMultiThreader(const vtkMultiThreader&) = delete; void operator=(const vtkMultiThreader&) = delete; }; using ThreadInfoStruct = vtkMultiThreader::ThreadInfo; #endif