|
1
|
1 #pragma once
|
|
|
2
|
|
|
3 #include <functional>
|
|
|
4
|
|
|
5 //! Generic service for receiving notifications about async operation completion. Used by various other services.
|
|
|
6 class completion_notify : public service_base {
|
|
|
7 public:
|
|
|
8 //! Called when an async operation has been completed. Note that on_completion is always called from main thread. You can use on_completion_async() helper if you need to signal completion while your context is in another thread.\n
|
|
|
9 //! IMPLEMENTATION WARNING: If process being completed creates a window taking caller's window as parent, you must not destroy the parent window inside on_completion(). If you need to do so, use PostMessage() or main_thread_callback to delay the deletion.
|
|
|
10 //! IMPLEMENTATION NOTE: on_completion() couldn't be declared noexcept in base class for historical reasons, but it's recommended that your overrides of on_completion() are noexcept.
|
|
|
11 //! @param p_code Context-specific status code. Possible values depend on the operation being performed.
|
|
|
12 virtual void on_completion(unsigned p_code) = 0;
|
|
|
13
|
|
|
14 //! Helper. Queues a notification, using main_thread_callback.
|
|
|
15 void on_completion_async(unsigned p_code);
|
|
|
16
|
|
|
17 //! Helper. Checks for null ptr and calls on_completion_async when the ptr is not null.
|
|
|
18 static void g_signal_completion_async(service_ptr_t<completion_notify> p_notify,unsigned p_code);
|
|
|
19
|
|
|
20 FB2K_MAKE_SERVICE_INTERFACE(completion_notify,service_base);
|
|
|
21 };
|
|
|
22
|
|
|
23 //! Implementation helper.
|
|
|
24 class completion_notify_dummy : public completion_notify {
|
|
|
25 public:
|
|
|
26 void on_completion(unsigned) override {}
|
|
|
27 };
|
|
|
28
|
|
|
29 //! Implementation helper.
|
|
|
30 class completion_notify_orphanable : public completion_notify {
|
|
|
31 public:
|
|
|
32 virtual void orphan() = 0;
|
|
|
33 };
|
|
|
34
|
|
|
35 //! Helper implementation.
|
|
|
36 //! IMPLEMENTATION WARNING: If process being completed creates a window taking caller's window as parent, you must not destroy the parent window inside on_task_completion(). If you need to do so, use PostMessage() or main_thread_callback to delay the deletion.
|
|
|
37 template<typename t_receiver>
|
|
|
38 class completion_notify_impl : public completion_notify_orphanable {
|
|
|
39 public:
|
|
|
40 void on_completion(unsigned p_code) {
|
|
|
41 if (m_receiver != NULL) {
|
|
|
42 m_receiver->on_task_completion(m_taskid,p_code);
|
|
|
43 }
|
|
|
44 }
|
|
|
45 void setup(t_receiver * p_receiver, unsigned p_task_id) {m_receiver = p_receiver; m_taskid = p_task_id;}
|
|
|
46 void orphan() {m_receiver = NULL; m_taskid = 0;}
|
|
|
47 private:
|
|
|
48 t_receiver * m_receiver;
|
|
|
49 unsigned m_taskid;
|
|
|
50 };
|
|
|
51
|
|
|
52 template<typename t_receiver>
|
|
|
53 service_nnptr_t<completion_notify_orphanable> completion_notify_create(t_receiver * p_receiver,unsigned p_taskid) {
|
|
|
54 service_nnptr_t<completion_notify_impl<t_receiver> > instance = new service_impl_t<completion_notify_impl<t_receiver> >();
|
|
|
55 instance->setup(p_receiver,p_taskid);
|
|
|
56 return instance;
|
|
|
57 }
|
|
|
58
|
|
|
59 typedef service_ptr_t<completion_notify> completion_notify_ptr;
|
|
|
60 typedef service_ptr_t<completion_notify_orphanable> completion_notify_orphanable_ptr;
|
|
|
61 typedef service_nnptr_t<completion_notify> completion_notify_nnptr;
|
|
|
62 typedef service_nnptr_t<completion_notify_orphanable> completion_notify_orphanable_nnptr;
|
|
|
63
|
|
|
64 //! Helper base class for classes that manage nonblocking tasks and get notified back thru completion_notify interface.
|
|
|
65 class completion_notify_receiver {
|
|
|
66 public:
|
|
|
67 completion_notify::ptr create_or_get_task(unsigned p_id);
|
|
|
68 completion_notify_ptr create_task(unsigned p_id);
|
|
|
69 bool have_task(unsigned p_id) const;
|
|
|
70 void orphan_task(unsigned p_id);
|
|
|
71 ~completion_notify_receiver();
|
|
|
72 void orphan_all_tasks();
|
|
|
73
|
|
|
74 virtual void on_task_completion(unsigned p_id,unsigned p_status) {(void)p_id;(void)p_status;}
|
|
|
75 private:
|
|
|
76 static void orphanfunc(unsigned,completion_notify_orphanable_nnptr p_item) {p_item->orphan();}
|
|
|
77 pfc::map_t<unsigned,completion_notify_orphanable_nnptr> m_tasks;
|
|
|
78 };
|
|
|
79
|
|
|
80 namespace fb2k {
|
|
|
81
|
|
|
82 typedef std::function<void (unsigned)> completionNotifyFunc_t;
|
|
|
83
|
|
|
84 //! Modern completion_notify helper
|
|
|
85 completion_notify::ptr makeCompletionNotify( completionNotifyFunc_t );
|
|
|
86 }
|