forked from CobaltFusion/DebugViewPP
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProcessMonitor.cpp
More file actions
93 lines (82 loc) · 2.44 KB
/
Copy pathProcessMonitor.cpp
File metadata and controls
93 lines (82 loc) · 2.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// (C) Copyright Gert-Jan de Vos and Jan Wilmans 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <array>
#include "Win32/Win32Lib.h"
#include "DebugViewppLib/ProcessMonitor.h"
namespace fusion {
namespace debugviewpp {
ProcessMonitor::ProcessInfo::ProcessInfo(DWORD pid, HANDLE handle) :
pid(pid),
handle(handle)
{
}
ProcessMonitor::ProcessMonitor() :
m_end(false),
m_event(Win32::CreateEvent(nullptr, false, false, nullptr)),
m_thread([this] { Run(); })
{
}
ProcessMonitor::~ProcessMonitor()
{
assert((m_end == true) && "Abort was not called, thread still running...");
}
void ProcessMonitor::Add(DWORD pid, HANDLE handle)
{
m_q.Push([this, pid, handle] {
m_processes.emplace_back(ProcessMonitor::ProcessInfo(pid, handle));
});
Win32::SetEvent(m_event);
}
boost::signals2::connection ProcessMonitor::ConnectProcessEnded(ProcessEnded::slot_type slot)
{
return m_processEnded.connect(slot);
}
void ProcessMonitor::Run()
{
size_t offset = 0;
while (!m_end)
{
std::array<HANDLE, MAXIMUM_WAIT_OBJECTS> handles;
handles[0] = m_event.get();
size_t processCount = m_processes.size();
auto count = std::min<size_t>(processCount, MAXIMUM_WAIT_OBJECTS - 1);
for (size_t i = 0; i < count; ++i)
{
handles[i + 1] = m_processes[(offset + i) % processCount].handle;
}
DWORD timeout = static_cast<size_t>(count) < m_processes.size() ? 1000 : INFINITE;
auto result = Win32::WaitForAnyObject(handles.data(), handles.data() + count + 1, timeout);
if (!result.signaled)
{
offset = (offset + count) % processCount;
}
else if (result.index == 0)
{
while (!m_q.Empty())
{
m_q.Pop()();
}
}
else
{
size_t i = (offset + result.index - 1) % processCount;
m_processEnded(m_processes[i].pid, m_processes[i].handle);
m_processes[i] = m_processes.back();
m_processes.resize(processCount - 1);
}
}
}
void ProcessMonitor::Abort()
{
m_processEnded.disconnect_all_slots();
if (m_thread.joinable())
{
m_q.Push([this] { m_end = true; });
Win32::SetEvent(m_event);
m_thread.join();
}
}
} // namespace debugviewpp
} // namespace fusion