1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #ifndef META_API_DEFERRED_CALLBACK_H
16 #define META_API_DEFERRED_CALLBACK_H
17
18 #include <meta/base/interface_traits.h>
19 #include <meta/interface/interface_helpers.h>
20 #include <meta/interface/intf_lifecycle.h>
21 #include <meta/interface/intf_task_queue.h>
22 #include <meta/interface/simple_event.h>
23
24 META_BEGIN_NAMESPACE();
25
26 /**
27 * @brief Implementation of ITaskQueueTask for deferred calls.
28 */
29 template<typename Func>
30 class QueueTask : public IntroduceInterfaces<ITaskQueueTask> {
31 META_INTERFACE(IntroduceInterfaces<ITaskQueueTask>, QueueTask, "426c3d10-89e5-4cf7-a314-a5155ede1595");
32
33 public:
QueueTask(Func func)34 QueueTask(Func func) : func_(BASE_NS::move(func)) {}
35
Invoke()36 bool Invoke() override
37 {
38 func_();
39 return false;
40 }
41
42 private:
43 Func func_;
44 };
45
46 template<typename Func, typename Interface, typename Signature = typename Interface::FunctionType>
47 class DeferredCallable;
48
49 /**
50 * @brief Implementation of callable for deferred calls.
51 */
52 template<typename Func, typename Interface, typename... Args>
53 class DeferredCallable<Func, Interface, void(Args...)> : public IntroduceInterfaces<Interface> {
54 template<typename F>
55 struct ControlBlock {
ControlBlockControlBlock56 ControlBlock(F f) : func_(BASE_NS::move(f)) {}
57
CallControlBlock58 void Call(Args... args) const
59 {
60 func_(args...);
61 }
62
63 private:
64 const F func_;
65 };
66
67 public:
DeferredCallable(Func func,const ITaskQueue::Ptr & q)68 DeferredCallable(Func func, const ITaskQueue::Ptr& q)
69 : control_(new ControlBlock<Func>(BASE_NS::move(func))), queue_(q)
70 {}
71
72 /*
73 ~DeferredCallable()
74 {
75 // todo: implement to make sure there is no call in progress any more
76 // either by using the task queue, or with synchronisation primitives
77 }
78 */
Invoke(Args...args)79 void Invoke(Args... args) override
80 {
81 auto q = queue_.lock();
82 if (q) {
83 q->AddTask(ITaskQueueTask::Ptr(new QueueTask([control = BASE_NS::weak_ptr(control_), args...]() mutable {
84 auto p = control.lock();
85 if (p) {
86 p->Call(args...);
87 }
88 })));
89 }
90 }
91
92 private:
93 BASE_NS::shared_ptr<ControlBlock<Func>> control_;
94 ITaskQueue::WeakPtr queue_;
95 };
96
97 /**
98 * @brief Make deferred callable from callable entity (e.g. lambda) by giving callable interface.
99 * @param func Callable entity which is invoked.
100 * @param queue Task queue that the call is posted to.
101 */
102 template<typename CallableInterface, typename Func,
103 typename = EnableIfCanInvokeWithArguments<Func, typename CallableInterface::FunctionType>>
MakeDeferred(Func func,const ITaskQueue::Ptr & queue)104 auto MakeDeferred(Func func, const ITaskQueue::Ptr& queue)
105 {
106 using DType = DeferredCallable<Func, CallableInterface>;
107 return typename DType::Ptr(new DType(BASE_NS::move(func), queue));
108 }
109 META_END_NAMESPACE();
110 #endif
111