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/impl/codegen/completion_queue.h>
28 #include <grpcpp/impl/codegen/completion_queue_tag.h>
29 #include <grpcpp/impl/codegen/grpc_library.h>
30 #include <grpcpp/impl/codegen/time.h>
31 #include <grpcpp/impl/grpc_library.h>
32 
33 namespace grpc {
34 
35 class Alarm : private ::grpc::GrpcLibraryCodegen {
36  public:
37   /// Create an unset completion queue alarm
38   Alarm();
39 
40   /// Destroy the given completion queue alarm, cancelling it in the process.
41   ~Alarm() override;
42 
43   /// DEPRECATED: Create and set a completion queue alarm instance associated to
44   /// \a cq.
45   /// This form is deprecated because it is inherently racy.
46   /// \internal We rely on the presence of \a cq for grpc initialization. If \a
47   /// cq were ever to be removed, a reference to a static
48   /// internal::GrpcLibraryInitializer instance would need to be introduced
49   /// here. \endinternal.
50   template <typename T>
Alarm(::grpc::CompletionQueue * cq,const T & deadline,void * tag)51   Alarm(::grpc::CompletionQueue* cq, const T& deadline, void* tag) : Alarm() {
52     SetInternal(cq, ::grpc::TimePoint<T>(deadline).raw_time(), tag);
53   }
54 
55   /// Trigger an alarm instance on completion queue \a cq at the specified time.
56   /// Once the alarm expires (at \a deadline) or it's cancelled (see \a Cancel),
57   /// an event with tag \a tag will be added to \a cq. If the alarm expired, the
58   /// event's success bit will be true, false otherwise (ie, upon cancellation).
59   template <typename T>
Set(::grpc::CompletionQueue * cq,const T & deadline,void * tag)60   void Set(::grpc::CompletionQueue* cq, const T& deadline, void* tag) {
61     SetInternal(cq, ::grpc::TimePoint<T>(deadline).raw_time(), tag);
62   }
63 
64   /// Alarms aren't copyable.
65   Alarm(const Alarm&) = delete;
66   Alarm& operator=(const Alarm&) = delete;
67 
68   /// Alarms are movable.
Alarm(Alarm && rhs)69   Alarm(Alarm&& rhs) noexcept : alarm_(rhs.alarm_) { rhs.alarm_ = nullptr; }
70   Alarm& operator=(Alarm&& rhs) noexcept {
71     alarm_ = rhs.alarm_;
72     rhs.alarm_ = nullptr;
73     return *this;
74   }
75 
76   /// Cancel a completion queue alarm. Calling this function over an alarm that
77   /// has already fired has no effect.
78   void Cancel();
79 
80 #ifdef GRPC_CALLBACK_API_NONEXPERIMENTAL
81   /// Set an alarm to invoke callback \a f. The argument to the callback
82   /// states whether the alarm expired at \a deadline (true) or was cancelled
83   /// (false)
84   template <typename T>
Set(const T & deadline,std::function<void (bool)> f)85   void Set(const T& deadline, std::function<void(bool)> f) {
86     SetInternal(::grpc::TimePoint<T>(deadline).raw_time(), std::move(f));
87   }
88 #endif
89 
90   /// NOTE: class experimental_type is not part of the public API of this class
91   /// TODO(vjpai): Move these contents to the public API of Alarm when
92   ///              they are no longer experimental
93   class experimental_type {
94    public:
experimental_type(Alarm * alarm)95     explicit experimental_type(Alarm* alarm) : alarm_(alarm) {}
96 
97     /// Set an alarm to invoke callback \a f. The argument to the callback
98     /// states whether the alarm expired at \a deadline (true) or was cancelled
99     /// (false)
100     template <typename T>
Set(const T & deadline,std::function<void (bool)> f)101     void Set(const T& deadline, std::function<void(bool)> f) {
102       alarm_->SetInternal(::grpc::TimePoint<T>(deadline).raw_time(),
103                           std::move(f));
104     }
105 
106    private:
107     Alarm* alarm_;
108   };
109 
110   /// NOTE: The function experimental() is not stable public API. It is a view
111   /// to the experimental components of this class. It may be changed or removed
112   /// at any time.
experimental()113   experimental_type experimental() { return experimental_type(this); }
114 
115  private:
116   void SetInternal(::grpc::CompletionQueue* cq, gpr_timespec deadline,
117                    void* tag);
118   void SetInternal(gpr_timespec deadline, std::function<void(bool)> f);
119 
120   ::grpc::internal::CompletionQueueTag* alarm_;
121 };
122 
123 }  // namespace grpc
124 
125 #endif  // GRPCPP_ALARM_H
126