Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: installer/src/installer-lib/process.h

Issue 5665210325008384: Combine snapshot classes into a template class (Closed)
Patch Set: Created April 3, 2014, 4:51 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « installer/src/installer-lib/handle.h ('k') | installer/src/installer-lib/process.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: installer/src/installer-lib/process.h
===================================================================
--- a/installer/src/installer-lib/process.h
+++ b/installer/src/installer-lib/process.h
@@ -5,6 +5,7 @@
#ifndef PROCESS_H
#define PROCESS_H
+#include "installer-lib.h"
#include "handle.h"
#include <string>
@@ -63,7 +64,6 @@
typedef std::basic_string< wchar_t, ci_traits< wchar_t > > wstring_ci ;
-
//-------------------------------------------------------
// file_name_set: case-insensitive wide-string set
//-------------------------------------------------------
@@ -167,7 +167,71 @@
// Snapshot
//-------------------------------------------------------
/**
- * A snapshot of all the processes running on the system.
+ * Traits class for snapshots of all processes on the system.
+ */
+struct Process_Snapshot_Traits
+{
+ /**
+ * The type of the data resulting from CreateToolhelp32Snapshot.
+ */
+ typedef PROCESSENTRY32W result_type ;
+
+ /**
+ * Flags used to call CreateToolhelp32Snapshot.
+ */
+ const static DWORD snapshot_flags = TH32CS_SNAPPROCESS ;
+
+ /**
+ * Wrapper for 'first' function for processes
+ */
+ static BOOL first( HANDLE arg1, LPPROCESSENTRY32 arg2 )
+ {
+ return ::Process32First( arg1, arg2 ) ;
+ }
+
+ /**
+ * Wrapper for 'next' function for processes
+ */
+ static BOOL next( HANDLE arg1, LPPROCESSENTRY32 arg2 )
+ {
+ return ::Process32Next( arg1, arg2 ) ;
+ }
+} ;
+
+/**
+ * Traits class for snapshots of all modules loaded by a process.
+ */
+struct Module_Snapshot_Traits
+{
+ /**
+ * The type of the data resulting from CreateToolhelp32Snapshot.
+ */
+ typedef MODULEENTRY32W result_type ;
+
+ /**
+ * Flags used to call CreateToolhelp32Snapshot.
+ */
+ const static DWORD snapshot_flags = TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32 ;
+
+ /**
+ * Wrapper for 'first' function for modules
+ */
+ static BOOL first( HANDLE arg1, LPMODULEENTRY32 arg2 )
+ {
+ return ::Module32First( arg1, arg2 ) ;
+ }
+
+ /**
+ * Wrapper for 'next' function for modules
+ */
+ static BOOL next( HANDLE arg1, LPMODULEENTRY32 arg2 )
+ {
+ return ::Module32Next( arg1, arg2 ) ;
+ }
+} ;
+
+/**
+ * A snapshot wrapping the results of CreateToolhelp32Snapshot system call.
*
* Unfortunately, we cannot provide standard iterator for this class.
* Standard iterators must be copy-constructible, which entails the possibility of multiple, coexisting iteration states.
@@ -175,9 +239,7 @@
* Thus, there can be only one iterator at a time for the snapshot.
* The two requirements are not simultaneously satisfiable.
*
- * As a substitute for a standard iterator, we provide a few functions mimicking the pattern of standard iterators.
- * This class acts as its own iterator.
- * The pointer returned is either one to the member variable "process" or else 0.
+ * Instead of a standard iterator, we provide a first() and next() functions wrapping the corresponding system calls.
*
* \par Implementation
*
@@ -185,18 +247,41 @@
* - MSDN [Process32First function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684834%28v=vs.85%29.aspx)
* - MSDN [Process32Next function](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684836%28v=vs.85%29.aspx)
* - MSDN [PROCESSENTRY32 structure](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684839%28v=vs.85%29.aspx)
+ *
+ * \par Design Note
+ * The traits class defines first() and next() functions instead of using function pointers.
+ * This arises from a limitation in the compiler.
+ * The system calls are declared 'WINAPI', which is a compiler-specific extension.
+ * That extension, however, does not go far enough to be able to declare a pointer with the same modifier.
+ * Hence the system calls must be called directly; they are wrapped in the trait functions.
*/
+template< class Traits >
class Snapshot
{
+public:
/**
- * Handle to the process snapshot.
+ * Expose the result type from the traits class as our own.
+ */
+ typedef typename Traits::result_type result_type ;
+
+private:
+ /**
+ * Process ID argument for CreateToolhelp32Snapshot.
+ */
+ DWORD _id ;
+
+ /**
+ * Handle to the underlying snapshot.
*/
Windows_Handle handle ;
/**
* Buffer for reading a single process entry out of the snapshot.
+ *
+ * This buffer is constant insofar as the code outside this class is concerned.
+ * The accessor functions first() and next() return pointers to constant result_type.
*/
- PROCESSENTRY32W process;
+ result_type buffer;
/**
* Copy constructor declared private and not defined.
@@ -214,77 +299,101 @@
*/
Snapshot operator=( const Snapshot & ) ;
+ /**
+ * Create a new snapshot and return its handle.
+ */
+ Windows_Handle::handle_type make_handle()
+ {
+ Windows_Handle::handle_type h = ::CreateToolhelp32Snapshot( Traits::snapshot_flags, _id ) ;
+ if ( h == INVALID_HANDLE_VALUE )
+ {
+ throw windows_api_error( "CreateToolhelp32Snapshot", "INVALID_HANDLE_VALUE" ) ;
+ }
+ return h ;
+ }
+
+protected:
+ /**
+ * Constructor takes a snapshot.
+ */
+ Snapshot( DWORD id )
+ : _id( id ), handle( make_handle() )
+ {
+ // The various result types all define 'dwSize' with the same semantics.
+ buffer.dwSize = sizeof( result_type ) ;
+ }
public:
/**
- * Default constructor takes the snapshot.
+ * Reconstruct the current instance with a new system snapshot.
+ *
+ * This function uses reinitialization assignment in the Windows_Handle class,
+ * which takes care of closing the old handle.
*/
- Snapshot() ;
+ void refresh()
+ {
+ handle = make_handle();
+ }
/**
- * Reconstruct the current instance with a new system snapshot.
+ * Retrieve the first snapshot item into our member buffer.
+ *
+ * \return
+ * Pointer to our member buffer if there was a first item
+ * 0 otherwise
+ *
+ * \par Design Note
+ * There's no error handling in the present version of this function.
+ * In part that's because the underlying system call returns either true or false, both of which are ordinarily valid answers.
+ * The trouble is that a false return is overloaded.
+ * It can mean either that (ordinary) there are no more items or (exceptional) the snapshot did not contain the right kind of item.
+ * GetLastError is no help here; it doesn't distinguish between these cases.
+ * The upshot is that we rely that our implementation calls the right functions on the snapshot,
+ * and so we ignore the case where we've passed bad arguments to the system call.
*/
- void refresh() ;
+ const result_type * first()
+ {
+ return Traits::first(handle, &buffer) ? &buffer : 0;
+ }
/**
- * Return a pointer to the first process in the snapshot.
+ * Retrieve the next snapshot item into our member buffer and return a pointer to it.
+ * begin() must have been called first.
+ *
+ * \return
+ * Pointer to our member buffer if there was a first item
+ * 0 otherwise
+ *
+ * \par Design Note
+ * See the Design Note for first(); the same considerations apply here.
*/
- PROCESSENTRY32W * first() ;
-
- /**
- * Return a pointer to the next process in the snapshot.
- * begin() must have been called first.
- */
- PROCESSENTRY32W * next() ;
+ const result_type * next()
+ {
+ return Traits::next(handle, &buffer) ? &buffer : 0;
+ }
} ;
-class ModulesSnapshot
+/**
+ * A snapshot of all processes running on the system.
+ */
+struct Process_Snapshot
+ : public Snapshot< Process_Snapshot_Traits >
{
- /**
- * Handle to the process snapshot.
- */
- Windows_Handle handle;
+ Process_Snapshot()
+ : Snapshot( 0 )
+ {}
+} ;
- /**
- * Buffer for reading a single module entry out of the snapshot.
- */
- MODULEENTRY32W module;
-
- /**
- * Copy constructor declared private and not defined.
- *
- * \par Implementation
- * Add "= delete" for C++11.
- */
- ModulesSnapshot(const ModulesSnapshot&);
-
- /**
- * Copy assignment declared private and not defined.
- *
- * \par Implementation
- * Add "= delete" for C++11.
- */
- ModulesSnapshot operator=(const ModulesSnapshot&);
-
-
-public:
- /**
- * Default constructor takes the snapshot.
- */
- ModulesSnapshot(DWORD processId);
-
- /**
- * Return a pointer to the first process in the snapshot.
- */
- MODULEENTRY32W* first();
-
- /**
- * Return a pointer to the next process in the snapshot.
- * begin() must have been called first.
- */
- MODULEENTRY32W* next();
-};
-
+/**
+ * A snapshot of all modules loaded for a given process.
+ */
+struct Module_Snapshot
+ : public Snapshot< Module_Snapshot_Traits >
+{
+ Module_Snapshot( DWORD process_id )
+ : Snapshot( process_id )
+ {}
+} ;
//-------------------------------------------------------
// initialize_process_list
@@ -299,10 +408,10 @@
* \param convert A conversion function that takes a PROCESSENTRY32W as input argument and returns an element of type T.
*/
template<class T, class Admittance, class Extractor>
-void initialize_process_list(std::vector<T>& v, Snapshot& snap, Admittance admit = Admittance(), Extractor extract = Extractor())
+void initialize_process_list(std::vector<T>& v, Process_Snapshot &snap, Admittance admit = Admittance(), Extractor extract = Extractor())
{
- PROCESSENTRY32W* p = snap.first();
- while (p != NULL)
+ const PROCESSENTRY32W* p = snap.first();
+ while (p != 0)
{
if (admit(*p ))
{
@@ -329,10 +438,10 @@
* \param convert A conversion function that takes a PROCESSENTRY32W as input argument and returns an element of type T.
*/
template<class T, class Admittance, class Extractor>
-void initialize_process_set(std::set< T > & set, Snapshot& snap, Admittance admit = Admittance(), Extractor extract = Extractor())
+void initialize_process_set(std::set< T > & set, Process_Snapshot &snap, Admittance admit = Admittance(), Extractor extract = Extractor())
{
- PROCESSENTRY32W* p = snap.first();
- while (p != NULL)
+ const PROCESSENTRY32W* p = snap.first();
+ while (p != 0)
{
if (admit(*p))
{
@@ -514,7 +623,7 @@
/**
* Snapshot of running processes.
*/
- Snapshot & snapshot ;
+ Process_Snapshot & snapshot ;
void update()
{
@@ -556,13 +665,13 @@
public:
template <size_t n_file_names, size_t n_module_names>
- Process_Closer(Snapshot & snapshot, const wchar_t* (&file_name_list)[n_file_names], const wchar_t* (&module_name_list)[n_module_names])
+ Process_Closer(Process_Snapshot & snapshot, const wchar_t* (&file_name_list)[n_file_names], const wchar_t* (&module_name_list)[n_module_names])
: snapshot(snapshot), process_names(file_name_list), module_names(module_name_list), filter(process_names, module_names)
{
update() ;
}
template <size_t n_file_names>
- Process_Closer(Snapshot & snapshot, const wchar_t * (&file_name_list)[n_file_names])
+ Process_Closer(Process_Snapshot & snapshot, const wchar_t * (&file_name_list)[n_file_names])
: snapshot(snapshot), process_names(file_name_list), module_names(), filter(process_names, module_names)
{
update() ;
« no previous file with comments | « installer/src/installer-lib/handle.h ('k') | installer/src/installer-lib/process.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld