1/*
2    Title:      Task farm for Multi-Threaded Garbage Collector
3
4    Copyright (c) 2010-12 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.
28class GCTaskId {
29
30};
31
32extern 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.
37typedef void (*gctask)(GCTaskId*, void*, void*);
38
39typedef struct {
40    gctask  task;
41    void    *arg1;
42    void    *arg2;
43} queue_entry;
44
45class GCTaskFarm {
46public:
47    GCTaskFarm();
48    ~GCTaskFarm();
49
50    bool Initialise(unsigned threadCount, unsigned queueSize);
51
52    bool AddWork(gctask task, void *arg1, void *arg2);
53    void AddWorkOrRunNow(gctask task, void *arg1, void *arg2);
54    void WaitForCompletion(void);
55    void Terminate(void);
56    // See if the queue is draining.  Used as a hint as to whether
57    // it's worth sparking off some new work.
58    bool Draining(void) const { return queuedItems == 0; }
59
60    unsigned ThreadCount(void) const { return threadCount; }
61
62private:
63    // The semaphore is zero if there is no work or some value up to
64    // the number of threads if there is work.
65    PSemaphore waitForWork;
66    // The lock protects the queue and the item count.
67    PLock workLock;
68    // The condition variable is signalled when the queue is empty.
69    // This can only be waited for by a single thread because it's not a proper
70    // implementation of a condition variable in Windows.
71    PCondVar waitForCompletion;
72    unsigned queueSize, queueIn, queuedItems;
73    queue_entry *workQueue; // Array of unit->unit functions.
74    bool terminate; // Set to true to kill all workers.
75    unsigned threadCount; // Count of workers.
76    unsigned activeThreadCount; // Count of workers doing work.
77
78    void ThreadFunction(void);
79
80#if ((!defined(_WIN32) || defined(__CYGWIN__)) && defined(HAVE_PTHREAD_H))
81    static void *WorkerThreadFunction(void *parameter);
82    pthread_t *threadHandles;
83#elif defined(HAVE_WINDOWS_H)
84    static DWORD WINAPI WorkerThreadFunction(void *parameter);
85    HANDLE *threadHandles;
86#endif
87};
88
89#endif
90
91