summaryrefslogtreecommitdiffstats
path: root/src/include/usr/util/threadpool.H
blob: c04b7bede344d6a0ea3640e6a48a7c5a7715690e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/include/usr/util/threadpool.H $                           */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2012                   */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#ifndef __UTIL_THREADPOOL_H
#define __UTIL_THREADPOOL_H

/** @file threadpool.H
 *  @brief Defines the interfaces for a thread-pool.
 *
 *  Provides two classes, one of which is templatized: ThreadPool and
 *  ThreadPoolManager.
 *
 *  ThreadPool is an implementation of a thread-pool.  It accepts a template
 *  parameter of the class describing the work that can be done by this
 *  thread-pool.  The only requirement is that this class provides an
 *  operator().
 *
 *  The default behavior of the ThreadPool is to be a FIFO.  If the desire is
 *  for the ThreadPool to operate in a non-FIFO manner then the work item
 *  class must support less-than comparison.  The pool will then execute the
 *  oldest work item (a) such that all other work items (b) have:
 *      (false == (b < a))
 *
 *  Work Item Prototypes:
 *      void operator()() { ... execute work ... }
 *      bool operator<(const WorkItem& rhs);
 *
 *  ThreadPoolManager can be used to globally control the number of threads
 *  started when a new thread pool is started.  The intent of this class is
 *  that the maximum number of threads will be adjusted by an the IPL step
 *  management based on the phase of the IPL we are in.  When we are cache
 *  contained the number should be kept lower and when we exit cache contained
 *  we can allow much more parallelism.
 *
 */

#include <stdint.h>
#include <util/traits/has_lessthan.H>
#include <util/impl/threadpool.H>

namespace Util
{

/**
 * @brief Definition of the thread pool.
 *
 * @param[in] WorkItem - The class to accept as the work.
 *
 * The thread-pool will execute the operator() on WorkItems.  Work will be done
 * in a FIFO manner unless the < comparison works on the WorkItems, in which
 * case the oldest WorkItem for which all other work items fail (b<a) will be
 * processed.
 *
 * The thread-pool will only create worker threads once the 'start' operation
 * has been called.  When the 'shutdown' operation is called, the thread-pool
 * will complete its outstanding work and destroy all children worker threads.
 *
 * @note The thread-safety of this object ensures that it is self-consistent
 *       between insert and worker-thread operations but does not protect
 *       against multiple threads calling the start / shutdown operations.
 *       Multiple threads may insert safely but only one thread should be
 *       responsible for the state management.
 */
template <typename WorkItem>
class ThreadPool : public Util::__Util_ThreadPool_Impl::ThreadPoolImpl
{
    public:
            /** Basic Constructor.  Initialize ThreadPool. */
        ThreadPool() : Util::__Util_ThreadPool_Impl::ThreadPoolImpl() { };
            /** Basic Destructor.  Ensures pool is properly shut down. */
        ~ThreadPool() { shutdown(); };

            /** @brief Creates worker threads and begins processing work.
             */
        void start()
            {
                __start(reinterpret_cast<start_fn_t>(&run), this);
            };
            /** @brief Completes outstanding work and destroys worker threads.
             *
             *  @note This function will block until all work is completed and
             *        worker threads are destroyed.
             */
        void shutdown()
            { __shutdown(); };

            /** @brief Insert a work item onto the thread-pool's queue.
             *
             *  Ownership of the object is transfered to the thread-pool.
             *  After completing the work, the thread-pool will delete the
             *  work item.
             *
             *  @param[in] i_workItem - A work item to process.
             */
        void insert(WorkItem* i_workitem)
            { __insert(i_workitem); };

    private:
            /** Entry point for worker thread. */
        static void* run(ThreadPool*);
            /** Useful constant to determine FIFO vs non-FIFO behavior. */
        static const bool has_comparison =
                Util::Traits::has_lessthan<WorkItem>::value;
};

/**
 * @brief Manager of the thread pools.
 *
 * When new thread-pools are created, they query the manager to determine
 * how many worker threads to create.  This should be manipulated by some
 * higher level service that understands the resources available to
 * thread-pools and sets the value to balance memory usage and efficiency.
 */
class ThreadPoolManager
{
    public:
        /** Query the desired worker-thread count. */
        static size_t getThreadCount()
            { return cv_size; };
        /** Set the desired worker-thread count. */
        static void setThreadCount(size_t i_size)
            { cv_size = i_size; };
    private:
        static size_t cv_size;
};

// Implementation of the worker-thread run function.
template <typename WorkItem>
void* ThreadPool<WorkItem>::run(
        ThreadPool<WorkItem>* self)
{
    while(1)
    {
        // Obtain next work item from queue.
        WorkItem* wi =
            static_cast<WorkItem*>(
                self->__remove(
                    reinterpret_cast<order_fn_t>(
                        &Util::__Util_ThreadPool_Impl::ThreadPoolWorklistSearch
                            <WorkItem, has_comparison>::search
                    )
                )
            );

        if (wi) // Work was given, do it.
        {
            (*wi)();
            delete wi;
        }
        else // No work item was given, we must be done.
        {
            return NULL; // task_end() called automatically by returning.
        }
    }
    return NULL;
}

};

#endif
OpenPOWER on IntegriCloud