12a8eac92STrond Norbye/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
22a8eac92STrond Norbye/*
32a8eac92STrond Norbye *     Copyright 2015 Couchbase, Inc.
42a8eac92STrond Norbye *
52a8eac92STrond Norbye *   Licensed under the Apache License, Version 2.0 (the "License");
62a8eac92STrond Norbye *   you may not use this file except in compliance with the License.
72a8eac92STrond Norbye *   You may obtain a copy of the License at
82a8eac92STrond Norbye *
92a8eac92STrond Norbye *       http://www.apache.org/licenses/LICENSE-2.0
102a8eac92STrond Norbye *
112a8eac92STrond Norbye *   Unless required by applicable law or agreed to in writing, software
122a8eac92STrond Norbye *   distributed under the License is distributed on an "AS IS" BASIS,
132a8eac92STrond Norbye *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142a8eac92STrond Norbye *   See the License for the specific language governing permissions and
152a8eac92STrond Norbye *   limitations under the License.
162a8eac92STrond Norbye */
172a8eac92STrond Norbye
182a8eac92STrond Norbye#include "executorpool.h"
192a8eac92STrond Norbye#include "task.h"
202a8eac92STrond Norbye
212a8eac92STrond Norbye#include <cstdlib>
222a8eac92STrond Norbye#include <iostream>
232a8eac92STrond Norbye#include <string>
242a8eac92STrond Norbye
254a6a43c1SWill GardnerExecutorPool::ExecutorPool(size_t sz)
264a6a43c1SWill Gardner    : ExecutorPool(sz, cb::defaultProcessClockSource()) {
274a6a43c1SWill Gardner}
284a6a43c1SWill Gardner
294a6a43c1SWill GardnerExecutorPool::ExecutorPool(size_t sz, cb::ProcessClockSource& clock) {
302a8eac92STrond Norbye    roundRobin.store(0);
312a8eac92STrond Norbye    executors.reserve(sz);
322a8eac92STrond Norbye    for (size_t ii = 0; ii < sz; ++ii) {
334a6a43c1SWill Gardner        executors.emplace_back(createWorker(clock));
342a8eac92STrond Norbye    }
352a8eac92STrond Norbye}
362a8eac92STrond Norbye
372a8eac92STrond Norbyevoid ExecutorPool::schedule(std::shared_ptr<Task>& task, bool runnable) {
382a8eac92STrond Norbye    if (task->getMutex().try_lock()) {
392a8eac92STrond Norbye        task->getMutex().unlock();
402a8eac92STrond Norbye        throw std::logic_error(
412a8eac92STrond Norbye            "The mutex should be held when trying to schedule a event");
422a8eac92STrond Norbye    }
432a8eac92STrond Norbye
442a8eac92STrond Norbye    executors[++roundRobin % executors.size()]->schedule(task, runnable);
452a8eac92STrond Norbye}
46fd603705SWill Gardner
47fd603705SWill Gardnervoid ExecutorPool::clockTick() {
48fd603705SWill Gardner    for (const auto& executor : executors) {
49fd603705SWill Gardner        executor->clockTick();
50fd603705SWill Gardner    }
51fd603705SWill Gardner}
524a6a43c1SWill Gardner
534a6a43c1SWill Gardnersize_t ExecutorPool::waitqSize() const {
544a6a43c1SWill Gardner    size_t count = 0;
554a6a43c1SWill Gardner    for (const auto& executor : executors) {
564a6a43c1SWill Gardner        count += executor->waitqSize();
574a6a43c1SWill Gardner    }
584a6a43c1SWill Gardner    return count;
594a6a43c1SWill Gardner}
604a6a43c1SWill Gardner
614a6a43c1SWill Gardnersize_t ExecutorPool::runqSize() const {
624a6a43c1SWill Gardner    size_t count = 0;
634a6a43c1SWill Gardner    for (const auto& executor : executors) {
644a6a43c1SWill Gardner        count += executor->runqSize();
654a6a43c1SWill Gardner    }
664a6a43c1SWill Gardner    return count;
674a6a43c1SWill Gardner}
684a6a43c1SWill Gardner
694a6a43c1SWill Gardnersize_t ExecutorPool::futureqSize() const {
704a6a43c1SWill Gardner    size_t count = 0;
714a6a43c1SWill Gardner    for (const auto& executor : executors) {
724a6a43c1SWill Gardner        count += executor->futureqSize();
734a6a43c1SWill Gardner    }
744a6a43c1SWill Gardner    return count;
754a6a43c1SWill Gardner}
76