1 //
2 //
3 // Copyright 2015 gRPC authors.
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 //
18 
19 /// An Alarm posts the user-provided tag to its associated completion queue or
20 /// invokes the user-provided function on expiry or cancellation.
21 #ifndef GRPCPP_ALARM_H
22 #define GRPCPP_ALARM_H
23 
24 #include <functional>
25 
26 #include <grpc/grpc.h>
27 #include <grpcpp/completion_queue.h>
28 #include <grpcpp/impl/completion_queue_tag.h>
29 #include <grpcpp/impl/grpc_library.h>
30 #include <grpcpp/support/time.h>
31 
32 namespace grpc {
33 
34 class Alarm : private grpc::internal::GrpcLibrary {
35  public:
36   /// Create an unset completion queue alarm
37   Alarm();
38 
39   /// Destroy the given completion queue alarm, cancelling it in the process.
40   ~Alarm() override;
41 
42   /// DEPRECATED: Create and set a completion queue alarm instance associated to
43   /// \a cq.
44   /// This form is deprecated because it is inherently racy.
45   /// \internal We rely on the presence of \a cq for grpc initialization. If \a
46   /// cq were ever to be removed, a reference to a static
47   /// internal::GrpcLibraryInitializer instance would need to be introduced
48   /// here. \endinternal.
49   template <typename T>
Alarm(grpc::CompletionQueue * cq,const T & deadline,void * tag)50   Alarm(grpc::CompletionQueue* cq, const T& deadline, void* tag) : Alarm() {
51     SetInternal(cq, grpc::TimePoint<T>(deadline).raw_time(), tag);
52   }
53 
54   /// Trigger an alarm instance on completion queue \a cq at the specified time.
55   /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
56   /// an event with tag \a tag will be added to \a cq. If the alarm expired, the
57   /// event's success bit will be true, false otherwise (ie, upon cancellation).
58   //
59   // USAGE NOTE: This is frequently used to inject arbitrary tags into \a cq by
60   // setting an immediate deadline. Such usage allows synchronizing an external
61   // event with an application's \a grpc::CompletionQueue::Next loop.
62   template <typename T>
Set(grpc::CompletionQueue * cq,const T & deadline,void * tag)63   void Set(grpc::CompletionQueue* cq, const T& deadline, void* tag) {
64     SetInternal(cq, grpc::TimePoint<T>(deadline).raw_time(), tag);
65   }
66 
67   /// Alarms aren't copyable.
68   Alarm(const Alarm&) = delete;
69   Alarm& operator=(const Alarm&) = delete;
70 
71   /// Alarms are movable.
Alarm(Alarm && rhs)72   Alarm(Alarm&& rhs) noexcept : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
73   Alarm& operator=(Alarm&& rhs) noexcept {
74     std::swap(alarm_, rhs.alarm_);
75     return *this;
76   }
77 
78   /// Cancel a completion queue alarm. Calling this function over an alarm that
79   /// has already fired has no effect.
80   void Cancel();
81 
82   /// Set an alarm to invoke callback \a f. The argument to the callback
83   /// states whether the alarm expired at \a deadline (true) or was cancelled
84   /// (false)
85   template <typename T>
Set(const T & deadline,std::function<void (bool)> f)86   void Set(const T& deadline, std::function<void(bool)> f) {
87     SetInternal(grpc::TimePoint<T>(deadline).raw_time(), std::move(f));
88   }
89 
90  private:
91   void SetInternal(grpc::CompletionQueue* cq, gpr_timespec deadline, void* tag);
92   void SetInternal(gpr_timespec deadline, std::function<void(bool)> f);
93 
94   grpc::internal::CompletionQueueTag* alarm_;
95 };
96 
97 }  // namespace grpc
98 
99 #endif  // GRPCPP_ALARM_H
100