fbcode: __x__-protect all __attribute__ keywords, mechanically
[folly.git] / folly / wangle / Executor.h
1 /*
2  * Copyright 2014 Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *   http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #pragma once
18
19 #include <boost/noncopyable.hpp>
20 #include <chrono>
21 #include <functional>
22 #include <memory>
23 #include <stdexcept>
24
25 namespace folly { namespace wangle {
26   /// An Executor accepts units of work with add(), which should be
27   /// threadsafe.
28   /// Like an Rx Scheduler. We should probably rename it to match now that it
29   /// has scheduling semantics too, but that's a codemod for another lazy
30   /// summer afternoon.
31   class Executor : boost::noncopyable {
32    public:
33      typedef std::function<void()> Action;
34      // Reality is that better than millisecond resolution is very hard to
35      // achieve. However, we reserve the right to be incredible.
36      typedef std::chrono::microseconds Duration;
37      typedef std::chrono::steady_clock::time_point TimePoint;
38
39      virtual ~Executor() = default;
40
41      /// Enqueue an action to be performed by this executor. This and all
42      /// schedule variants must be threadsafe.
43      virtual void add(Action&&) = 0;
44
45      /// A convenience function for shared_ptr to legacy functors.
46      ///
47      /// Sometimes you have a functor that is move-only, and therefore can't be
48      /// converted to a std::function (e.g. std::packaged_task). In that case,
49      /// wrap it in a shared_ptr (or maybe folly::MoveWrapper) and use this.
50      template <class P>
51      void addPtr(P fn) {
52        this->add([fn]() mutable { (*fn)(); });
53      }
54
55      /// Alias for add() (for Rx consistency)
56      void schedule(Action&& a) { add(std::move(a)); }
57
58      /// Schedule an action to be executed after dur time has elapsed
59      /// Expect millisecond resolution at best.
60      void schedule(Action&& a, Duration const& dur) {
61        scheduleAt(std::move(a), now() + dur);
62      }
63
64      /// Schedule an action to be executed at time t, or as soon afterward as
65      /// possible. Expect millisecond resolution at best. Must be threadsafe.
66      virtual void scheduleAt(Action&& a, TimePoint const& t) {
67        throw std::logic_error("unimplemented");
68      }
69
70      /// Get this executor's notion of time. Must be threadsafe.
71      virtual TimePoint now() {
72        return std::chrono::steady_clock::now();
73      }
74   };
75 }}