1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
5 * Copyright (C) 2016 Red Hat Inc.
14 #include "boost/variant.hpp"
16 #include "ssched_recs.h"
24 namespace simple_scheduler {
26 template<typename C, typename R, typename Time>
31 using RequestRef = std::unique_ptr<R>;
33 // a function to see whether the server can handle another request
34 using CanHandleRequestFunc = std::function<bool(void)>;
36 // a function to submit a request to the server; the second
37 // parameter is a callback when it's completed
38 using HandleRequestFunc =
39 std::function<void(const C&,RequestRef,NullData)>;
42 enum class Type { returning, none };
50 boost::variant<Retn> data;
55 enum class Mechanism { push, pull };
62 bool finishing = false;
65 CanHandleRequestFunc can_handle_f;
66 HandleRequestFunc handle_f;
68 mutable std::mutex queue_mtx;
69 using DataGuard = std::lock_guard<decltype(queue_mtx)>;
71 std::deque<QRequest> queue;
75 ProfileTimer<std::chrono::nanoseconds> pull_request_timer;
76 ProfileTimer<std::chrono::nanoseconds> add_request_timer;
77 ProfileTimer<std::chrono::nanoseconds> request_complete_timer;
83 // push full constructor
84 SimpleQueue(CanHandleRequestFunc _can_handle_f,
85 HandleRequestFunc _handle_f) :
86 mechanism(Mechanism::push),
87 can_handle_f(_can_handle_f),
94 mechanism(Mechanism::pull)
103 void add_request(R&& request,
105 const ReqParams& req_params) {
106 add_request(RequestRef(new R(std::move(request))),
107 client_id, req_params);
110 void add_request(RequestRef&& request,
112 const ReqParams& req_params) {
113 DataGuard g(queue_mtx);
116 add_request_timer.start();
118 queue.emplace_back(QRequest{client_id, std::move(request)});
120 if (Mechanism::push == mechanism) {
125 add_request_timer.stop();
129 void request_completed() {
130 assert(Mechanism::push == mechanism);
131 DataGuard g(queue_mtx);
134 request_complete_timer.start();
139 request_complete_timer.stop();
141 } // request_completed
143 PullReq pull_request() {
144 assert(Mechanism::pull == mechanism);
146 DataGuard g(queue_mtx);
149 pull_request_timer.start();
153 result.type = PullReq::Type::none;
155 auto front = queue.front();
156 result.type = PullReq::Type::returning;
158 typename PullReq::Retn{front.client, std::move(front.request)};
163 pull_request_timer.stop();
171 // queue_mtx should be held when called; should only be called
172 // when mechanism is push
173 void schedule_request() {
174 if (!queue.empty() && can_handle_f()) {
175 auto& front = queue.front();
176 static NullData null_data;
177 handle_f(front.client, std::move(front.request), null_data);