C++で名前付きパイプサーバーを作成しようとしています。私はパイプのインスタンスのコンテナを含むclient_pool
というクラスと、接続されたすべてのクライアントに非同期でデータを送信する単一のpublicメンバ関数write
を持っています。宣言後にフレンドクラスを追加する
問題は、クライアントが突然切断される傾向があることです。この場合、WriteFileEx
へのコールはで失敗します。それが起こると、私はclient_pool
クラスに行き、クライアントハンドルを閉じてそれをコンテナから削除するように指示します。しかし、WriteFileEx
は使いにくいので、匿名の名前空間にwrite_context
というヘルパークラスを作成しました。
だから、最終的な結果は、私がclients.cpp
で宣言されたクラスwrite_context
から、clients.h
で宣言されているclient_pool
でプライベートメソッドを、呼び出したいこと、です。 (省略取り扱い詳細/エラー)そのような何か:
clients.h
class client_pool {
struct implementation;
std::unique_ptr<implementation> pimpl;
public:
void write(uint8_t *data, size_t size);
};
clients.cpp
明らかstruct client_pool::implementation {
set<HANDLE> connected;
// ...
void disconnect(HANDLE victim)
{
CloseHandle(victim);
connected.erase(victim);
}
};
namespace { struct write_context {
OVERLAPPED overlapped;
client_pool *owner;
HANDLE target;
const uint8_t *buffer;
size_t total_size;
size_t written;
// ...
void next_chunk()
{
if(!WriteFileEx(/* ... */, write_context::completion_routine)) {
if(GetLastError() == ERROR_NO_DATA) {
// I want to do something like
owner->pimpl->disconnect(target);
}
}
}
static void CALLBACK completion_routine(DWORD errcode, DWORD transferred, LPOVERLAPPED overlapped)
{
auto self = reinterpret_cast<write_context*>(overlapped);
self->written += transferred;
if(errcode == ERROR_MORE_DATA) {
self->next_chunk();
} else {
delete self;
}
}
}; }
void client_pool::write(uint8_t *data, size_t size)
{
for each handle in pimpl->connected {
auto context = new write_context(this, handle, data, size);
context->next_chunk();
}
}
、pimpl
ので、コンパイルされませんowner->pimpl->disconnect(target);
ラインプライベートです。私は何ができますか/私のオルタナティブは何ですか?
ジェラルドの解決策ほどきれいではありませんが、アップコートのために十分にハックします。 –