2016-02-29 41 views
9

muszę rozwijać C++ rutynowego wykonywania tego pozornie trywialne zadanie: stworzyć plik tylko wtedy, gdy nie istnieje jeszcze zrobić nic/błąd podbić.Tworzenie nowego pliku unikanie warunków wyścigu

Ponieważ potrzebuję uniknąć warunków wyścigu, chcę użyć zasady "poproś o wybaczenie, a nie pozwolenie" (tj. Usiłowania zamierzonej operacji i sprawdzenia, czy się udało, w przeciwieństwie do wcześniejszego sprawdzenia warunków wstępnych), co według mojej wiedzy , jest jedyną niezawodną i przenośną metodą do tego celu [Wikipedia article][an example with getline].

Mimo to, nie mogłem znaleźć sposób, aby wdrożyć go w moim przypadku. Najlepsze co mogę wymyślić to otwieranie trybu fstream w trybie app (lub fopen z "a"), sprawdzanie pozycji wyjściowej za pomocą tellp (C++) lub ftell (C) i przerywanie, jeśli taka pozycja nie jest równa zero. Ma to jednak dwie wady, a mianowicie, że jeśli plik istnieje, zostanie zablokowany (choć przez krótki czas) i zmieni się jego data modyfikacji.

Sprawdziłem inne możliwe kombinacje ios_base::openmode dla fstream, jak również mode ciągi fopen ale nie znalazł opcję, która nadaje się do moich potrzeb. Dalsze wyszukiwanie w standardowych bibliotekach C i C++ oraz Boost Filesystem okazały się bezowocne.

Czy ktoś może wskazać metodę wykonać swoje zadanie w solidnej sposób (bez skutków zabezpieczenia, ma warunków wyścigu) bez konieczności korzystania z funkcji specyficznych dla systemu operacyjnego? Mój specyficzny problem dotyczy systemu Windows, ale preferowane byłyby rozwiązania przenośne.

EDYTOWANIE: Odpowiedź BitWhistlera całkowicie rozwiązuje problem programów C. Mimo to jestem zdumiony, że nie istnieje żadne rozwiązanie idiomatyczne w C++. Każdy z nich używa atrybutu open z atrybutem O_EXCL, zgodnie z propozycją Andrew Henle, który jest jednak zależny od systemu operacyjnego (w systemie Windows atrybut ten nosi nazwę _O_EXCL z dodatkowym podkreśleniem [MSDN]) lub osobno kompiluje plik C11 i łączy go z kodem C++ . Co więcej, otrzymany deskryptor pliku nie może zostać przekonwertowany na strumień z wyjątkiem niestandardowych rozszerzeń (np. GCC __gnu_cxx::stdio_filebuf). Mam nadzieję, że przyszła wersja C++ zaimplementuje podkatrybut "x" i ewentualnie także odpowiedni modyfikator dla strumieni plików.

+0

Chcesz uniknąć warunków wyścig pomiędzy kilku nitek lub kilku procesów? – user2807083

+3

Jaki jest twój system operacyjny? POSIX zapewnia ['open (filename, O_CREAT | O_EXCL ...)'] (http://pubs.opengroup.org/onlinepubs/009695399/functions/open.html), aby zrobić to, co chcesz zrobić. –

+1

Win32 API pozwala na to. Wiem to na pewno. –

Odpowiedz

3

Nowy standard C (C2011, który nie jest częścią C++) dodaje nowy standardowy podcyfrator ("x"), który można dołączyć do dowolnego specyfikatora "w" (w celu utworzenia "wx", "wbx", "w + x" lub "w + bx"/"wb + x"). Ten podokeculator zmusza funkcję do niepowodzenia, jeśli plik istnieje, zamiast go nadpisywać.

źródło: http://www.cplusplus.com/reference/cstdio/fopen/