4

システムで実行中のすべてのプロセスを列挙する入力反復子型を設計しています。

これは、プロセス内のモジュールを列挙するために私が設計した反復子に似ています。モジュール反復子は、コンストラクターで「プロセス」オブジェクトを受け取り、デフォルトで構築された反復子は、オフザエンド反復子と見なされます。

例:

hadesmem::ModuleIterator beg(process);
hadesmem::ModuleIterator end;
assert(beg != end);

ただし、イテレータに与える必要がある「状態」や情報がないため、プロセスの列挙についてどうすればよいかわかりません (すべては、Windows API を使用してイテレータによって内部的に処理されます)。

例:

// This is obviously a broken design, what is the best way to distinguish between the two?
hadesmem::ProcessIterator beg;
hadesmem::ProcessIterator end;

この状況に対処するための慣用的な方法は何ですか? つまり、イテレータ コンストラクタに何も指定する必要がない場合に、「新しい」イテレータの作成とオフザエンド イテレータの作成を区別する必要がある場合。

関連する場合は、VC11、GCC 4.7、および ICC 12.1 でサポートされている限り、このライブラリで C++11 を使用できます。

ありがとう。

編集:

明確にするために、私が上に投稿した形式では 2 つを区別することはできないことを知っているので、私が求めているのは、何よりも「デザイン」の質問です...多分私は何かを見落としているだけです明らかですが(初めてではありません)。

4

3 に答える 3

2

本当にやりたいことは、一種の ProcessList オブジェクトを作成し、それに基づいて反復子を作成することです。イテレータをインクリメントするたびに、すべてのプロセスまたは何かを列挙したくありません。

于 2012-06-18T18:01:28.283 に答える
1

繰り返し処理しているスナップショットを表すパラメータを保持するクラスを作成するCreateToolhelp32Snapshot()と、イテレータの自然なファクトリができます。このようなものが動作するはずです (私は Windows を使用していないため、テストされていません):

class Process;
class Processes {
    DWORD what, who;
public:
    Processes(DWORD what, DWORD who) : what(what), who(who) {}

    class const_iterator {
        HANDLE snapshot;
        LPPROCESSENTRY32 it;
        explicit const_iterator(HANDLE snapshot, LPPROCESSENTRY32 it)
            : snapshot(snapshot), it(it) {}
    public:
        const_iterator() : snapshot(0), it(0) {}

        // the two basic functions, implement iterator requirements with these:
        const_iterator &advance() {
            assert(snapshot);
            if ( it && !Process32Next(snapshot, &it))
                it = 0;
            return *this;
        }
        const Process dereference() const {
            assert(snapshot); assert(it);
            return Process(it);
        }
        bool equals(const const_iterator & other) const {
            return handle == other.handle && it == other.it;
        }
    };

    const_iterator begin() const {
        const HANDLE snapshot = CreateToolhelp32Snapshot(what, who);
        if (snapshot) {
            LPPROCESSENTRY32 it;
            if (Process32First(snapshot, &it))
                return const_iterator(snapshot, it);
        }
        return end();
    }
    const_iterator end() const {
        return const_iterator(snapshot, 0);
    }
};

inline bool operator==(Processes::const_iterator lhs, Processes::const_iterator rhs) {
    return lhs.equals(rhs);
}
inline bool operator!=(Processes::const_iterator lhs, Processes::const_iterator rhs) {
    return !operator==(lhs, rhs);
}

使用法:

int main() {
    const Processes processes( TH32CS_SNAPALL, 0 );
    for ( const Process & p : processes )
        // ...
    return 0;
}
于 2012-06-18T18:34:57.313 に答える
1

名前付きコンストラクタイディオムを使用できます。

class ProcessIterator
private:
    ProcessIterator(int) //begin iterator
    ProcessIterator(char) //end iterator
    //no default constructor, to prevent mistakes
public:
    friend ProcessIterator begin() {return ProcessIterator(0);}
    friend ProcessIterator end() {return ProcessIterator('\0');}
}

int main() {
    for(auto it=ProcessIterator::begin(); it!=ProcessIterator::end(); ++it)
        //stuff
}
于 2012-06-18T19:50:01.110 に答える