我正嘗試在C++中編寫一個命名管道服務器。我有一個名爲client_pool
的類,其中包含一個管道實例的容器和一個公共成員函數write
,它將數據異步地發送到所有連接的客戶端。聲明後添加好友類
問題是,客戶端有意外斷開的趨勢。發生這種情況時,WriteFileEx
的呼叫以失敗。當發生這種情況時,我想去client_pool
類,並告訴它關閉客戶端句柄並將其從容器中移除。但是,由於WriteFileEx
太難以使用,我在匿名命名空間中創建了一個名爲write_context
的助手類。
所以最終的結果是,我想打電話給在client_pool
私有方法,這是在clients.h
宣佈,從類write_context
,這是在clients.cpp
聲明。類似的東西(詳細信息/錯誤處理省略):
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();
}
}
顯然,線owner->pimpl->disconnect(target);
沒有編譯,因爲pimpl
是私人的。我能做什麼/我的替代品是什麼?
不像傑拉爾德的解決方案那麼幹淨,但對於upvote足夠的黑客。 –