C++로 명명 된 파이프 서버를 작성하려고합니다. 파이프 인스턴스의 컨테이너를 포함하는 client_pool
클래스와 연결된 모든 클라이언트에 비동기 적으로 데이터를 보내는 단일 공용 멤버 함수 write
이 있습니다.선언 후 친구 클래스 추가
문제는 클라이언트가 예기치 않게 연결이 끊기는 경향이 있다는 것입니다. 이 경우 WriteFileEx
에 대한 호출이 ERROR_NO_DATA
과 함께 실패합니다. 그런 일이 생기면 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();
}
}
, 라인 owner->pimpl->disconnect(target);
이 pimpl
때문에 컴파일되지 않습니다 비공개입니다. 나는 무엇을 할 수 있는가/나의 대안은 무엇인가?
friend void namespace_name::next_chunk()
또는 정적 기능은 내부 익명 네임 스페이스에있는 모든 여분의 물건이 배치 : 당신은 익명의 네임 스페이스 대신 명명 된 네임 스페이스를 사용하는 경우
제럴드의 솔루션만큼이나 깨끗하지는 않지만 upvote에 충분히 적합합니다. –