Я пытаюсь написать сервер именованных каналов на C ++. У меня есть класс с именем client_pool
, который содержит контейнер экземпляров канала и одну открытую функцию-член write
, которая асинхронно отправляет данные всем подключенным клиентам.
Проблема в том, что клиенты имеют тенденцию неожиданно отключаться. Когда это происходит, вызов на WriteFileEx
завершается неудачно с ERROR_NO_DATA
. Когда это происходит, я хочу перейти к классу 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
является приватной. Что я могу сделать / каковы мои заместители?