Nie mam bloga, więc wrzucaj tutaj.
Od jakiegoś czasu chodzi mi po głowie stworzenie wrapperów C++ na niektóre z systemowych API Windows.
Na próbę stworzyłem coś ułatwiającego korzystanie z Heap32ListNext
/ Module32Next
/ Process32Next
/ Thread32Next
.
Kodu jest niewiele, ale spędziłem trochę czasu zastanawiając się jak to w ogóle powinno działać. Jak mogą (i jak powinny) wyglądać iteratory - co nie jest to z początku wcale takie oczywiste: np. co to znaczy, że dwa iteratory są sobie równe albo jak powinna zachowywać się jego kopia. Wszystko to starałem się zrealizować przy jak najmniejszej ilości logiki w samym kodzie.
Pytania, komentarze i krytyka jak najbardziej wskazane.
Wymaga boosta (tylko nagłówki). Sprawdzone w VS2012 i GCC 4.7.2. Szkoda, że ten pierwszy nie ma constexpr
, bo obyłoby się bez kilku zbędnych linijek. Szkoda, że mingw jest w tyle z implementacją standardowego liba i musiałem zrezygnować z std::error_code
.
Sposób użycia:
for(auto& process : Snapshot::snapshot()->range<SnapshotProcessIterator>())
std::wcout << process.szExeFile << L"\n";
"Snapshot.hpp"
#ifndef __SNAPSHOT_ITERATOR_HPP__
#define __SNAPSHOT_ITERATOR_HPP__
#include <memory>
#include <stdexcept>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>
#include <boost/noncopyable.hpp>
#include <Windows.h>
#include <TlHelp32.h>
namespace rev { namespace system {
template<typename T>
struct SnapshotFunc
{
typedef BOOL (WINAPI *Func)(HANDLE, T*);
};
template<DWORD TFlag, typename T, typename SnapshotFunc<T>::Func TFuncFirst, typename SnapshotFunc<T>::Func TFuncNext>
struct SnapshotTraits
{
typedef T Object;
typedef typename SnapshotFunc<Object>::Func Func;
static const DWORD flag = TFlag;
static const Func funcFirst;
static const Func funcNext;
};
template<DWORD TFlag, typename T, typename SnapshotFunc<T>::Func TFuncFirst, typename SnapshotFunc<T>::Func TFuncNext>
const typename SnapshotFunc<T>::Func SnapshotTraits<TFlag, T, TFuncFirst, TFuncNext>::funcFirst = TFuncFirst;
template<DWORD TFlag, typename T, typename SnapshotFunc<T>::Func TFuncFirst, typename SnapshotFunc<T>::Func TFuncNext>
const typename SnapshotFunc<T>::Func SnapshotTraits<TFlag, T, TFuncFirst, TFuncNext>::funcNext = TFuncNext;
typedef SnapshotTraits<TH32CS_SNAPHEAPLIST, HEAPLIST32, Heap32ListFirst, Heap32ListNext> SnapshotHeaplistTraits;
typedef SnapshotTraits<TH32CS_SNAPMODULE, MODULEENTRY32, Module32First, Module32Next > SnapshotModuleTraits;
typedef SnapshotTraits<TH32CS_SNAPPROCESS, PROCESSENTRY32, Process32First, Process32Next > SnapshotProcessTraits;
typedef SnapshotTraits<TH32CS_SNAPTHREAD, THREADENTRY32, Thread32First, Thread32Next > SnapshotThreadTraits;
class Snapshot : boost::noncopyable, public std::enable_shared_from_this<Snapshot>
{
template <typename TTraits>
friend class SnapshotIterator;
HANDLE handle;
DWORD flags;
Snapshot(int processId, DWORD flags) : flags(flags) {
handle = CreateToolhelp32Snapshot(flags, processId);
if(!handle)
throw std::runtime_error("Cannot create snapshot");
}
public:
static std::shared_ptr<Snapshot> snapshot() {
return snapshot(0, TH32CS_SNAPPROCESS);
}
static std::shared_ptr<Snapshot> snapshot(int processId, DWORD flags = TH32CS_SNAPALL) {
return std::shared_ptr<Snapshot>(new Snapshot(processId, flags));
}
~Snapshot() {
CloseHandle(handle);
}
template <typename TIterator>
TIterator begin() {
if((flags & TIterator::Traits::flag) == 0)
throw std::runtime_error("Snapshot doesnt have data for specified iterator type");
return TIterator(shared_from_this());
}
template <typename TIterator>
TIterator end() {
return TIterator();
}
template <typename TIterator>
boost::iterator_range<TIterator> range() {
return boost::make_iterator_range(begin<TIterator>(), end<TIterator>());
}
};
template <typename TTraits>
class SnapshotIterator :
public boost::iterator_facade
<
SnapshotIterator<TTraits>,
const typename TTraits::Object,
boost::single_pass_traversal_tag
>
{
friend class Snapshot;
friend class boost::iterator_core_access;
typedef typename TTraits::Object Object;
std::shared_ptr<Snapshot> snapshot;
Object object;
const Object& dereference() const {
return object;
}
void increment() {
if(snapshot)
advance(TTraits::funcNext);
}
void advance(typename TTraits::Func func) {
object.dwSize = sizeof(Object);
if(!func(snapshot->handle, &object)) {
snapshot.reset();
if(GetLastError() != ERROR_NO_MORE_FILES)
throw std::runtime_error("Cannot get next value");
}
}
bool equal(const SnapshotIterator<TTraits>& other) const {
return snapshot == other.snapshot;
}
SnapshotIterator(std::shared_ptr<Snapshot> snapshot) : snapshot(snapshot) {
advance(TTraits::funcFirst);
}
public:
typedef TTraits Traits;
SnapshotIterator() { }
};
typedef SnapshotIterator<SnapshotHeaplistTraits> SnapshotHeaplistIterator;
typedef SnapshotIterator<SnapshotModuleTraits > SnapshotModuleIterator;
typedef SnapshotIterator<SnapshotProcessTraits > SnapshotProcessIterator;
typedef SnapshotIterator<SnapshotThreadTraits > SnapshotThreadIterator;
} } // namespace rev { namespace system {
#endif // ifdef __SNAPSHOT_ITERATOR_HPP__