Διεργασίες

sleep#

Παύει τη διεργασία για ένα πλήθος ακεραίων δευτερολέπτων.

Η sleep αναστέλλει την εκτέλεση της τρέχουσας διεργασίας για EXPR δευτερόλεπτα, ή - χωρίς όρισμα - μέχρι να την ξυπνήσει κάποιο σήμα. Το όρισμα αποκόπτεται σε ακέραιο· οι καθυστερήσεις κάτω του δευτερολέπτου απαιτούν διαφορετικό εργαλείο (βλ. παρακάτω). Η τιμή επιστροφής είναι ο αριθμός των δευτερολέπτων που κοιμήθηκε πραγματικά, που μπορεί να είναι μικρότερος από αυτόν που ζητήθηκε αν σήμα διέκοψε την κλήση.

Σύνοψη#

sleep EXPR
sleep

Τι επιστρέφεται#

Ένας ακέραιος: ο αριθμός των δευτερολέπτων κατά τα οποία ανεστάλη πραγματικά η διεργασία. Σε αδιακόπη κλήση αυτός ισούται με το (αποκομμένο) όρισμα. Αν ένα σήμα που παραδίδεται κατά τη διάρκεια του sleep αποδεσμεύσει την κλήση νωρίτερα, η τιμή επιστροφής είναι ο μικρότερος, πραγματικός χρόνος που πέρασε. Για γυμνή sleep, η τιμή είναι ό,τι κοιμήθηκε η υλοποίηση πριν φτάσει σήμα.

my $slept = sleep 10;
warn "woken early after $slept s" if $slept < 10;

Χειρισμός ορίσματος#

  • Θετικός ακέραιος - η κανονική περίπτωση. Κοιμάται για τόσα δευτερόλεπτα.

  • Μη ακέραιος (π.χ. 2.9) - το κλασματικό μέρος απορρίπτεται. Η sleep 2.9 κοιμάται δύο δευτερόλεπτα, όχι σχεδόν τρία. Για κλασματικές καθυστερήσεις χρησιμοποιήστε Time::HiRes::sleep, Time::HiRes::usleep, ή τη μορφή τεσσάρων ορισμάτων της select - βλ. παρακάτω.

  • Αρνητικός ακέραιος - η sleep δεν κοιμάται. Εκπέμπει προειδοποίηση, θέτει την $! (errno) και επιστρέφει μηδέν.

  • Μηδέν - η sleep 0 επιτρέπεται, αλλά εκτελεί παρ” όλα αυτά κλήση στη υποκείμενη πρωτογενή λειτουργία sleep της πλατφόρμας με όποιες παρενέργειες συνεπάγεται αυτή. Δεν είναι λοιπόν απολύτως ταυτόσημη με το να παραλείψετε την κλήση. Ειδικότερα, η sleep 0 δεν είναι το ίδιο με γυμνή sleep χωρίς όρισμα.

  • Κανένα όρισμα - η sleep χωρίς όρισμα κοιμάται επ” αόριστον, μέχρι να παραδοθεί σήμα. Αυτό διαφέρει από την sleep 0.

Διακοπή από σήματα#

Η sleep επιστρέφει νωρίτερα αν η διεργασία λάβει σήμα του οποίου ο χειριστής τρέχει (ή του οποίου η προεπιλεγμένη ενέργεια δεν τερματίζει τη διεργασία). Το κανονικό μοτίβο για μια οριοθετημένη αναμονή που μπορεί να ακυρωθεί από αλλού είναι μια alarm σε συνδυασμό με χειριστή σήματος:

eval {
    local $SIG{ALRM} = sub { die "Alarm!\n" };
    sleep;
};
die $@ unless $@ eq "Alarm!\n";

Επειδή η ίδια η sleep υλοποιείται συνήθως πάνω από την alarm σε συστήματα Unix, γενικά δεν μπορείτε να αναμίξετε κλήσεις alarm και sleep στο ίδιο πρόγραμμα χωρίς εκπλήξεις. Επιλέξτε μία.

Καθυστερήσεις κάτω του δευτερολέπτου#

Η sleep δέχεται εξ ορισμού μόνο ακεραίους. Για πιο λεπτόκοκκες αναμονές χρησιμοποιήστε ένα από τα:

  • Time::HiRes::sleep($seconds) - δέχεται κινητής υποδιαστολής αριθμό δευτερολέπτων. Από την Perl 5.8 το Time::HiRes διανέμεται με την βασική διανομή.

  • Time::HiRes::usleep($microseconds) - ακέραια microseconds.

  • Η μορφή τεσσάρων ορισμάτων της select με τα τρία πρώτα ορίσματα undef:

    select undef, undef, undef, 0.25;   # sleep 250 ms
    
  • syscall στη setitimer(2) αν η πλατφόρμα σας την υποστηρίζει και χρειάζεστε στενό έλεγχο πάνω σε χρονομετρητές.

Δείτε επίσης την POSIX::pause, που μπλοκάρει τη διεργασία μέχρι να φτάσει οποιοδήποτε σήμα - ουσιαστικά γυμνή sleep χωρίς όριο καθορισμένο από την υλοποίηση.

Παραδείγματα#

Σταθερή καθυστέρηση:

print "working...\n";
sleep 3;
print "done\n";

Βρόχος δημοσκόπησης με back-off:

until (ready()) {
    sleep 1;
}

Ανίχνευση πρόωρου ξυπνήματος:

my $want = 30;
my $got  = sleep $want;
if ($got < $want) {
    warn "interrupted after $got of $want seconds\n";
}

Αναμονή για σήμα χωρίς να καίγεται CPU - η γυμνή sleep αναστέλλει μέχρι να φτάσει SIGALRM (ή οποιοδήποτε άλλο σήμα που πιάνεται):

$SIG{USR1} = sub { warn "got USR1\n" };
sleep;                                  # wakes on USR1 delivery

Ακύρωση μακράς αναμονής με alarm:

eval {
    local $SIG{ALRM} = sub { die "timeout\n" };
    alarm 5;
    sleep 3600;                         # at most 5 seconds really
    alarm 0;
};
alarm 0;
die $@ if $@ && $@ ne "timeout\n";

Οριακές περιπτώσεις#

  • Η γυμνή sleep δεν κοιμάται πραγματικά «για πάντα». Η υλοποίηση έχει μέγιστο - στην πράξη, ό,τι δέχεται η υποκείμενη sleep(3) της C ή το ισοδύναμο - αλλά για κάθε ρεαλιστικό σκοπό μπλοκάρει μέχρι να φτάσει σήμα. Αντιμετωπίστε την ως αόριστη αναμονή.

  • sleep 0 ≠ καμία κλήση. Η κλήση συστήματος sleep(0) της πλατφόρμας εκτελείται παρ” όλα αυτά. Στα περισσότερα συστήματα αυτό παραχωρεί την CPU για λίγο· μη βασίζεστε στη συγκεκριμένη συμπεριφορά σε διαφορετικές πλατφόρμες.

  • Η sleep έναντι του πραγματικού χρόνου. Σε παλαιότερα συστήματα η sleep μπορούσε να επιστρέψει μέχρι και ένα ολόκληρο δευτερόλεπτο νωρίτερα λόγω αδρής μέτρησης δευτερολέπτων. Τα σύγχρονα συστήματα κοιμούνται ολόκληρη την ποσότητα, αλλά μπορούν να υπερβούν: ο χρονοπρογραμματιστής μπορεί να μην ξυπνήσει αμέσως τη διεργασία σας σε ένα απασχολημένο σύστημα. Η sleep N εγγυάται τουλάχιστον N δευτερόλεπτα αναστολής σε σύγχρονους πυρήνες, όχι ακριβώς N.

  • Τα αρνητικά ορίσματα δεν περικόπτονται. Είναι σκληρό no-op που θέτει την $!. Αν υπολογίζετε το όρισμα, επικυρώστε το πρώτα.

  • Η ανάμιξη με alarm είναι εύθραυστη. Ο χρονομετρητής alarm και ο χρονομετρητής sleep μπορεί να είναι ο ίδιος πόρος. Καθιερώστε μία πειθαρχία (είτε alarm + γυμνή sleep, είτε σκέτη sleep N χωρίς alarms) και μείνετε σε αυτήν μέσα σε ένα πρόγραμμα.

  • Σήματα που απλώς θέτουν σημαία επίσης ξυπνούν την sleep. Οποιοδήποτε σήμα του οποίου η παράδοση κάνει χειριστή να τρέξει επιστρέφει τον έλεγχο στην Perl· η sleep τότε επιστρέφει νωρίτερα ακόμη και αν ο ίδιος ο χειριστής δεν κάνει τίποτα ορατό.

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • alarm - προγραμματίζει SIGALRM μετά από δεδομένο αριθμό δευτερολέπτων· ο κλασικός τρόπος να οριοθετηθεί μια sleep ή οποιαδήποτε άλλη μπλοκαριστική κλήση

  • select - στη μορφή τεσσάρων ορισμάτων με μη ορισμένη τριάδα readfds/writefds/exceptfds, παρέχει sleeps κάτω του δευτερολέπτου

  • wait, waitpid - μπλοκάρει σε διεργασίες-παιδιά αντί σε χρόνο

  • Time::HiRes::sleep - δευτερόλεπτα κινητής υποδιαστολής

  • Time::HiRes::usleep - ακέραια microseconds

  • POSIX::pause - μπλοκάρει μέχρι να φτάσει οποιοδήποτε σήμα