1 /* 2 Title: Task farm for Multi-Threaded Garbage Collector 3 4 Copyright (c) 2010-12, 2019 David C. J. Matthews 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 20 */ 21 22 #ifndef GCTASKFARM_H_INCLUDED 23 #define GCTASKFARM_H_INCLUDED 24 25 #include "locking.h" 26 27 // An empty class just used as an ID. 28 class GCTaskId { 29 30 }; 31 32 extern GCTaskId *globalTask; // The ID used when a function is run immediately 33 34 // Function for action. The usual C++ approach would be to use an 35 // object pointer but that requires lots of small objects to be created 36 // and deleted. 37 typedef void (*gctask)(GCTaskId*, void*, void*); 38 39 typedef struct { 40 gctask task; 41 void *arg1; 42 void *arg2; 43 } queue_entry; 44 45 class GCTaskFarm { 46 public: 47 GCTaskFarm(); 48 ~GCTaskFarm(); 49 50 // Initialise and create the worker threads 51 bool Initialise(unsigned threadCount, unsigned queueSize); 52 // Set single threaded mode. This is only used in a child process after 53 // Posix fork in case there is a GC before the exec. SetSingleThreaded()54 void SetSingleThreaded() { threadCount = 0; queueSize = 0; } 55 56 bool AddWork(gctask task, void *arg1, void *arg2); 57 void AddWorkOrRunNow(gctask task, void *arg1, void *arg2); 58 void WaitForCompletion(void); 59 void Terminate(void); 60 // See if the queue is draining. Used as a hint as to whether 61 // it's worth sparking off some new work. Draining(void)62 bool Draining(void) const { return queuedItems == 0; } 63 ThreadCount(void)64 unsigned ThreadCount(void) const { return threadCount; } 65 66 private: 67 // The semaphore is zero if there is no work or some value up to 68 // the number of threads if there is work. 69 PSemaphore waitForWork; 70 // The lock protects the queue and the item count. 71 PLock workLock; 72 // The condition variable is signalled when the queue is empty. 73 // This can only be waited for by a single thread because it's not a proper 74 // implementation of a condition variable in Windows. 75 PCondVar waitForCompletion; 76 unsigned queueSize, queueIn, queuedItems; 77 queue_entry *workQueue; // Array of unit->unit functions. 78 bool terminate; // Set to true to kill all workers. 79 unsigned threadCount; // Count of workers. 80 unsigned activeThreadCount; // Count of workers doing work. 81 82 void ThreadFunction(void); 83 84 #if (!defined(_WIN32)) 85 static void *WorkerThreadFunction(void *parameter); 86 pthread_t *threadHandles; 87 #else 88 static DWORD WINAPI WorkerThreadFunction(void *parameter); 89 HANDLE *threadHandles; 90 #endif 91 }; 92 93 #endif 94 95