File: threadpool.cc

package info (click to toggle)
eclib 2014-09-21-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 4,216 kB
  • ctags: 4,287
  • sloc: cpp: 45,827; makefile: 222; sh: 108
file content (157 lines) | stat: -rw-r--r-- 4,511 bytes parent folder | download | duplicates (6)
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
// FILE threadpool.cc : Implementation of member functions for class threadpool
//////////////////////////////////////////////////////////////////////////
//
// Copyright 1990-2012 Marcus Mo
// 
// This file is part of the eclib package.
// 
// eclib is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version.
// 
// eclib is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// 
// You should have received a copy of the GNU General Public License
// along with eclib; if not, write to the Free Software Foundation,
// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
// 
//////////////////////////////////////////////////////////////////////////

/**
 * threadpool.cc
 *
 * Simple, no-frills threadpool for Boost threads.
 * Some features have been made available specifically for ECLIB.
 *
 * These include use of verbosity level in constructor, to be 
 * used for logging. Tasks must also have an overloaded
 * operator() which describes what each thread must perform on 
 * that object. The return value of the task must be
 * void, i.e. nothing is returned.
 */

// Compile this only if Boost is installed
#ifdef ECLIB_MULTITHREAD

// Include header files
#include "eclib/threadpool.h"

/**
 * Threadpool()
 *
 * Default constructor. Must call start() before using threadpool.
 */
threadpool::threadpool() 
  : maxThreads_( 0 ), threadCount_( 0 ), verbose_( -1 ),
    work_( new boost::asio::io_service::work( io_service_ ) )
{}

/**
 * threadpool()
 *
 * Main constructor.
 */
threadpool::threadpool( unsigned int numThreads, int verbose ) 
  : work_( new boost::asio::io_service::work( io_service_ ) ) {
  start( numThreads, verbose );
}

/**
 * ~Threadpool()
 *
 * Desctructor. Simply calls close() 
 */
threadpool::~threadpool() {
  close();
}

/**
 * start();
 *
 * Must be called after constructor, and allows for threadpool 
 * to be restarted after a call to close().
 */
void threadpool::start( unsigned int numThreads, int verbose ) {
  // Store verbosity
  verbose_ = verbose;

  // Store maximum number of threads system can support
  maxThreads_ = boost::thread::hardware_concurrency();

  // Store actual number of threads to be used.
  // If not specified, we use the system limit.
  threadCount_ = ( numThreads > 0 ) ? numThreads : maxThreads_;

  // We limit the number of threads to the system limit.
  // Note: it is best to not use all available threads
  if( threadCount_ > maxThreads_ ) {
    // Reset limit
    threadCount_ = maxThreads_;

    // Notify
    if( verbose_ ) std::cout << "Requested more threads than available." 
                            << std::endl; 
  }

  // Declare the final number of threads to be used
  if( verbose_ > 1 ) std::cout << "Threadpool will be using " << threadCount_ 
                               << " threads from a total of " 
                               << maxThreads_ << " threads." << std::endl;

  // Create threads and add to threadpool
  for( unsigned int i = 0; i < threadCount_-1; i++  ) {
    threads_.create_thread( boost::bind( &boost::asio::io_service::run, &io_service_ ) );
  }
}

/**
 * close()
 *
 * Closes io_service_ to prevent further
 * jobs added to job queue. Joins all threads in 
 * threadpool; currently running jobs are completed
 * before returning control to calling thread.
 *
 * This blocking method exists in case we wish 
 * to close the threadpool before end-of-scope,
 * or to detect when all previously posted 
 * jobs have finished.
 */
void threadpool::close() {
  // We destroy the work class on the io_service object
  // so that we can exit once all jobs posted have finished
  work_.reset();

  // run() blocks until all posted jobs have finished
  io_service_.run();

  // We close the threadpool and join all threads
  io_service_.stop();
  threads_.join_all();
}

/**
 * getThreadCount()
 *
 * Returns number of threads initiated 
 * in threadpool.
 */
unsigned int threadpool::getThreadCount() {
  return threadCount_;
}

/**
 * getMaxThreads()
 * 
 * Returns maximum number of threads available.
 * Provides easier access.
 */
unsigned int threadpool::getMaxThreads() {
  return maxThreads_;
}

#endif // ECLIB_MULTITHREAD