1 /* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /*
3  *     Copyright 2015 Couchbase, Inc.
4  *
5  *   Licensed under the Apache License, Version 2.0 (the "License");
6  *   you may not use this file except in compliance with the License.
7  *   You may obtain a copy of the License at
8  *
9  *       http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *   Unless required by applicable law or agreed to in writing, software
12  *   distributed under the License is distributed on an "AS IS" BASIS,
13  *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *   See the License for the specific language governing permissions and
15  *   limitations under the License.
16  */
17 #pragma once
18 
19 #include "executor.h"
20 
21 #include <memory>
22 #include <mutex>
23 #include <vector>
24 
25 /**
26  * As the name implies the ExecutorPool is pool of executors to execute
27  * tasks. A task is pinned to a thread when it is being scheduled
28  * (by using round robin) and never switch the thread.
29  */
30 class ExecutorPool {
31 public:
32     /**
33      * Create an executor pool with a given number of worker threads
34      * and the default clock source.
35      */
36     ExecutorPool(size_t sz);
37 
38     /**
39      * Create an executor pool with a given number of worker threads
40      * and an injected clock source
41      */
42     ExecutorPool(size_t sz, cb::ProcessClockSource& clock);
43 
44     ExecutorPool(const ExecutorPool &) = delete;
45 
46     /**
47      * Schedule a task for execution at some time. The tasks mutex
48      * must be held while calling this method to avoid race conditions.
49      *
50      * @param task the task to execute
51      * @param runnable is the task runnable, or should it be put in
52      *                 the wait queue..
53      */
54     void schedule(std::shared_ptr<Task>& task, bool runnable = true);
55 
56     /**
57      * This method should be called periodically (e.g. once a second)
58      * to make tasks that are scheduled to run the future runnable.
59      */
60     void clockTick();
61 
62     // @todo expose these as stats
63 
64     size_t waitqSize() const;
65 
66     size_t runqSize() const;
67 
68     size_t futureqSize() const;
69 
70 private:
71     /**
72      * The actual list of executors
73      */
74     std::vector< std::unique_ptr<Executor> > executors;
75 
76     /**
77      * We'll be using round robin to distribute the tasks to the
78      * worker threads
79      */
80     std::atomic_int roundRobin;
81 };
82