Bir std :: Future durumunu öğrenin


83

Bir std::futurebitip bitmediğini kontrol etmek mümkün mü ? Söyleyebildiğim kadarıyla, bunu yapmanın tek yolu wait_forsıfır süreli arama yapmak ve durumun olup olmadığını kontrol etmektir ready, ancak daha iyi bir yol var mı?


10
@CatPlusPlus Yanılmıyorsam, validsadece geleceğin paylaşılan bir durumu olup olmadığını kontrol ediyor (yani gelecekte çağrılana truekadar geri dönüyor get).
David Brown

Yani, getçağrıldıysa ve saklanan değeri döndürürse, yine de istiyor truemusunuz? (Değeri yalnızca bir kez alabileceğiniz için bunun neden yararlı olacağından emin değilim.)
James McNellis

@JamesMcNellis Belki de vadeli işlemleri yanlış anlıyorum veya yanlış kullanıyorum, ancak istediğim iş parçacığının (veya hesaplamayı yapan her neyse) bitip bitmediğini bilmek. QFuture::isFinishedTemelde Qt'nin eşdeğeri .
David Brown

1
Sıfır zaman aşımına sahip bir bekleme, birçok platformdaki çoğu API'nin böyle bir kavramla nasıl başa çıktığıdır ... Öyle ki, bunu kavrama yaklaşmanın "standart" yolu olarak düşünürdüm. Bu beni "daha iyi bir yol" kavramına biraz
şaşırttı

16
@asveikau Bunun standart bir uygulama olduğunun farkında değildim. Beklemek istemediğimde bekleme işlevini çağırmak garip geliyor.
David Brown

Yanıtlar:


85

Haklısınız wait_untilve geçmişte (eşdeğer olan) bir zamanla aramak dışında daha iyi bir yol yok.

Daha uygun bir sözdizimi istiyorsanız her zaman küçük bir sarmalayıcı yazabilirsiniz:

template<typename R>
  bool is_ready(std::future<R> const& f)
  { return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready; }

Not: Eğer işlev ertelenirse, bu asla doğru olmayacaktır, bu nedenle wait_forertelenen görevi belirli bir süre geçtikten sonra eşzamanlı olarak çalıştırmak isteyebileceğiniz durumda veya sistem yükü düşük olduğunda doğrudan kontrol etmek muhtemelen daha iyidir .


2
wait_for geleceği değiştirmez, bu nedenle parametre sabit olarak bildirilebilir.
Jens Åkerblom

7
Get zaten çağrıldıysa veya gelecek hiç başlatılmadıysa, çalışma zamanı hatalarını önlemek için önce valid () seçeneğini işaretlemeyi düşünün.
Jeremy Sorensen

5
Wait_for (chrono :: seconds (0)) 'ın hemen dönmesi garantili midir yoksa bazı uygulamalarda birkaç milisaniye için iş parçacığının kontrolünü sağlayabilir mi? Bir oyunu kodlarken birkaç milisaniye çok fazla zaman aldığından, bunu bilmek oldukça önemli olacaktır ...
kynnysmatto

9
@kynnysmatto, bazı uygulamalarda geleceğin durumunu güvenli bir şekilde incelemek için bir muteks kilidi edinir, bu nedenle bu kilit kontrol edilirse (çünkü başka bir iş parçacığı durumu hazır hale getiriyor veya hazır olup olmadığını kontrol ediyor) o zaman engelleyecek ve başka bir iş parçacığı çalışabilir, ancak iyi bir uygulamada muteks hiçbir zaman birkaç komuttan fazla tutulmamalıdır, yani tek bir milisaniye bile. GCC'nin şu anki uygulaması bir muteks kullanmıyor, ancak bir önceki yaptı ve durumu hazır hale getirmek iki işaretçiyi değiştirerek yapıldı, bu nedenle muteks sadece bu olurken çok kısa bir süre kilitlendi.
Jonathan Wakely

@JonathanWakely g ++ ile test etmek 43 for(int i = 0; i < 1000; i++) f.wait_for(chrono::seconds(0));ms duvar saati süresi alır.
Daniel Kinsman

15

Std :: future için çalışmalarda is_ready üye işlevi vardır . Bu arada, VC uygulamasının bir _Is_ready () üyesi vardır.


_Is_ready () üye işlevinin iş parçacığı için güvenli OLMADIĞINI unutmayın. İlişkili durumun _Ready bayrağına korumasız bir şekilde erişir. Bu, en azından VS2019 16.2 için geçerlidir.
Mattias De Charleroy

10

İlk bahsim wait_for0 süre ile aramak ve future_status::ready, future_status::deferredveya değerlerinden biri olabilecek sonuç kodunu kontrol etmek olacaktır future_status::timeout.

Gelen cppreference da iddia valid() sonuç varsa kontrolleri , ancak standart söylüyor valid()döndürür trueeğer *thispaylaşılan bir duruma işaret ettiği durum olup olmadığı, bağımsız bir şekilde, hazır ya da değil.


7
cppreference artık güncellendi ve "geleceğin paylaşılan bir durumu olup olmadığını denetler". (İkinci paragrafınızı kaldırmak mı yoksa düzenlemek mi istediğinizden emin değilim, bu yüzden kendim değiştirmeyeceğim).
Varsayılan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.