master
h 99 lines 3.08 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 Lifetime.h
8
9 Abstract:
10
11 This file contains function declarations around client lifetime.
12
13 --*/
14
15 #pragma once
16 #include <mutex>
17 #include <wil/resource.h>
18
19 class LifetimeManager
20 {
21 public:
22 LifetimeManager();
23 ~LifetimeManager();
24
25 LifetimeManager(const LifetimeManager&) = delete;
26 void operator=(const LifetimeManager&) = delete;
27 LifetimeManager(LifetimeManager&& source) = delete;
28
29 ULONG64 GetRegistrationId();
30
31 bool IsAnyProcessRegistered(_In_ ULONG64 ClientKey);
32
33 void RegisterCallback(_In_ ULONG64 ClientKey, _In_ const std::function<bool(void)>& Callback, _In_opt_ HANDLE ClientProcess, _In_ DWORD TimeoutMs = 0);
34
35 bool RemoveCallback(_In_ ULONG64 ClientKey);
36
37 void ClearCallbacks();
38
39 struct OwnedProcess
40 {
41 OwnedProcess();
42 ~OwnedProcess();
43 OwnedProcess(OwnedProcess&& other) noexcept;
44 void operator=(OwnedProcess&&) noexcept;
45 OwnedProcess(const OwnedProcess&) = delete;
46 void operator=(const OwnedProcess&) = delete;
47
48 void InitializeListenForTermination(_In_ PTP_WAIT_CALLBACK Callback, _In_ PVOID Context);
49 void ListenForTermination() const;
50
51 wil::unique_handle process;
52 wil::unique_threadpool_wait_nowait terminationWait;
53 };
54
55 struct ClientCallback
56 {
57 ClientCallback();
58 ~ClientCallback();
59 ClientCallback(ClientCallback&& other) noexcept;
60 void operator=(ClientCallback&&) noexcept;
61 ClientCallback(const ClientCallback&) = delete;
62 void operator=(const ClientCallback&) = delete;
63
64 void CancelTimer() const;
65 void CreateTimer(_In_ PTP_TIMER_CALLBACK Callback, _In_ PVOID Context);
66 std::list<OwnedProcess>::iterator FindProcess(_In_ HANDLE Process);
67 void SetTimer(_In_ DWORD DueTimeMs) const;
68
69 std::list<OwnedProcess> clientProcesses;
70 wil::unique_threadpool_timer_nowait timer;
71 ULONG64 clientKey{};
72 std::function<bool(void)> callback;
73 DWORD timeout{};
74 };
75
76 private:
77 _Requires_lock_held_(m_lock)
78 std::list<ClientCallback>::iterator _FindClient(_In_ ULONG64 ClientKey);
79
80 static VOID CALLBACK s_OnClientProcessTerminated(_Inout_ PTP_CALLBACK_INSTANCE, _Inout_opt_ PVOID Context, _Inout_ PTP_WAIT Wait, _In_ TP_WAIT_RESULT WaitResult);
81
82 static VOID CALLBACK s_OnTimeout(_Inout_ PTP_CALLBACK_INSTANCE Instance, _Inout_opt_ PVOID Context, _Inout_ PTP_TIMER Timer);
83
84 std::mutex m_lock;
85
86 _Guarded_by_(m_lock) bool m_exiting = false;
87
88 _Guarded_by_(m_lock) ULONG64 m_nextClientKey;
89
90 _Guarded_by_(m_lock) std::list<ClientCallback> m_callbackList;
91
92 // N.B. There is a race that could cause AV between callbacks firing and
93 // the destruction of the lifetime manager class. To avoid the race
94 // create a chain of waits where each callback waits for the previous
95 // callback to finish. The destructor of the class waits on the final
96 // callback before returning.
97 wil::unique_threadpool_wait m_lastCallbackWait;
98 wil::unique_threadpool_timer m_lastTimerWait;
99 };