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
);