c ++ - Hvad er et overlappet I/O-alternativ til WaitNamedPipe?

Indlæg af Hanne Mølgaard Plasc

Problem



Funktionen WaitNamedPipe gør det muligt for en rørklientprogram at synkrone vente på en tilgængelig forbindelse på en navngivet pipeserver. Du ringer derefter CreateFile for at åbne røret som en klient. Pseudokode: [21] [22]


// loop works around race condition with WaitNamedPipe and CreateFile
HANDLE hPipe;
while (true) {
    if (WaitNamedPipe says connection is ready) {
        hPipe = CreateFile(...);
        if (hPipe ok or last error is NOT pipe busy) {
            break; // hPipe is valid or last error is set
        }
    } else {
        break; // WaitNamedPipe failed
    }
}


Problemet er, at disse alle blokkerer, synkrone opkald. Hvad er en god måde at gøre dette asynkront på? Jeg kan f.eks. Ikke finde en API, der bruger overlappede I/O til at gøre dette. For eksempel giver ConnectNamedPipe funktionen lpOverlapped parametre for pip servere Rørserveren kan så ringe til WaitForMultipleObjects og vente på, at I/O-operationen er færdig, eller en anden begivenhed, der skal signaleres (for eksempel en begivenhed, der signalerer tråden for at annullere i afventning af I/O og opsige). [23] [24]


Den eneste måde, jeg kan tænke på, er at kalde WaitNamedPipe i en loop med en kort, endelig timeout og kontrollere andre signaler, hvis det går ud. Alternativt kan du i et sløjfeopkald CreateFile kontrollere andre signaler og derefter ringe Sleep med en kort forsinkelse (eller WaitNamedPipe). For eksempel:


HANDLE hPipe;
while (true) {
    hPipe = CreateFile(...);
    if (hPipe not valid and pipe is busy) {
        // sleep 100 milliseconds; alternatively, call WaitNamedPipe with timeout
        Sleep(100);
        // TODO: check other signals here to see if we should abort I/O
    } else
        break;
}


Men denne metode stinker til høj himmel efter min mening. Hvis et rør ikke er tilgængeligt i et stykke tid, fortsætter tråden med at løbe - suger op CPU'en ved hjælp af strøm, hvilket kræver, at hukommelsessider forbliver i RAM osv. I mit sind er en tråd, der er afhængig af Sleep eller korte timeouts fungerer ikke godt og er et tegn på sløret multi-threaded programmering.


Men hvad er alternativet i dette tilfælde?

Bedste reference


WaitNamedPipe er helt ubrugelig, og vil bare bruge alle cpu'erne, hvis du angiver en timeout, og der er ingen server, der venter på det.


Ring bare CreateFile igen og igen med en Sleep som du gør, og flyt den til andre tråde, som du finder passende. Der er ikke noget API-alternativ.


Den eneste 'fordel' WaitNamedPipe giver er, hvis du vil vide, om du kan oprette forbindelse til et navngivet rør, men du udtrykkeligt ikke ønsker at faktisk oprette forbindelse. Det er uønsket.


Hvis du virkelig vil være grundig, er dine eneste muligheder



  • Sørg for, at det program, der åbnes, kalder det navngivne rør altid CreateNamedPipe igen umiddelbart efter, at det kaldte rør er tilsluttet.

  • Få dit program til at kontrollere, om det pågældende program kører.

  • Hvis din hensigt ikke er at få yderligere forbindelser, skal du stadig ringe til CreateNamedPipe, og når nogen forbinder, skal du fortælle dem, at de skal gå væk, indtil de ventede en vis tid, lukker røret.


Andre referencer 1


Hvorfor kan ikke serveren bare lave flere rør? Ydelsen i det scenario du beskriver er ikke et problem, hvis det er sjældent.


Dvs. hvis der normalt er nok rør til at gå rundt, hvad betyder det, hvis du bruger CreateFile/Sleep i stedet for WaitForMultipleObjects? Resultatet slår ikke noget.


Jeg er også nødt til at stille spørgsmålstegn ved behovet for overlappende IO i en klient. Hvor mange servere kommunikerer det med ad gangen? Hvis svaret er mindre end, siger 10, kan du med rimelighed oprette en tråd pr. Forbindelse.


Dybest set siger jeg, at årsagen til, at der ikke er nogen overlappende WaitforNamedPipe, skyldes, at der ikke er nogen rimelig brugssag, der kræver det.