Δευτέρα 18 Ιανουαρίου 2016

Στατικές Μεταβλητές (Νέο) και Νήματα

Στην αναθεώρηση 140 έβαλα στατικές μεταβλητές και με αυτές και ακόμα μια εντολή έκανα επέκταση των νημάτων. Νήματα στη Μ2000 είναι κώδικας που τρέχει παράλληλα κάθε ένα καθορισμένο ελάχιστο χρόνο (μπορεί να πάρει και παραπάνω αν χρειάζεται).

Το δύσκολο με τις στατικές μεταβλητές σε μια γλώσσα που εκτελείται άμεσα (χωρίς δεύτερο πέρασμα) η οποία μπορεί να καλεί ένα τμήμα και αυτό ένα άλλο, δηλαδή να έχουμε μια "δενδρική" μορφή από τμήματα φωλιασμένα σε άλλα, είναι να βρει κανείς που θα τις βάλει!

Ένα τμήμα (όπως και μια συνάρτηση) στην Μ2000 τρέχει σε δικό του αντικείμενο εκτέλεσης. Οι μεταβλητές μπαίνουν σε ξεχωριστή λίστα εκτός αντικειμένου. Οι στατικές μεταβλητές όμως μπαίνουν στο αντικείμενο εκτέλεσης. Δεν μπορούμε να κάνουμε ορισμένα πράγματα με αυτές, όπως να τις περάσουμε με αναφορά. Κάθε φορά που ένα τμήμα τερματίζει παραδίδει στο προηγούμενο το πακέτο με τις στατικές μεταβλητές του (αν έχει). Οι αρχικές τιμές δίνονται εντός τμήματος και αν καλέσουμε το τμήμα τότε αν υπάρχουν οι μεταβλητές δεν θα πάρουν τις αρχικές τιμές. Αν καλέσουμε ένα τμήμα Μ με στατικές μεταβλητές από διαφορετικά τμήματα τότε το κάθε διαφορετικό τμήμα θα έχει την δική του κατάσταση αυτού του τμήματος Μ, όλα με δικό τους πακέτο στατικών για την Μ.

Το ενδιαφέρον με τις στατικές σχετίζεται με τα νήματα. Τα νήματα έχουν δικό τους αντικείμενο εκτέλεσης, δικό τους σωρό τιμών και δεν έχουν όνομα, παρά μόνο αριθμό χειρισμού. Βλέπουν τις μεταβλητές του τμήματος που ανήκουν, και ότι έχει αυτό σε τμήματα και συναρτήσεις και ρουτίνες (οι ρουτίνες δεν έχουν αντικείμενο εκτέλεσης, είναι κατασκευές/δομές εντός τμημάτων/συναρτήσεων). Έτσι όπως ήταν δεν είχαν πρόβλημα αλλά δεν μπορούσαν να "φυλάξουν" κάποια κατάσταση αν δεν είχαμε "ξεχωρίσει" τα νήματα (σαν να τα ονομάζαμε δηλαδή), ώστε σε καθένα να αντιστοιχούν διαφορετικές μεταβλητές. Αυτό σημαίνει ότι δεν θα έχουμε επαναλήψεις ίδιου νήματος. Με τις στατικές μεταβλητές μπορούμε να κρατήσουμε την κατάσταση των νημάτων χωρίς να μας ενδιαφέρει εν τέλει ο αριθμός αυτών που θέλουμε να τρέχουν μαζί.

Στα αγγλικά ένα νήμα είχε μέχρι τη 139 αναθεώρηση μια εντολή δημιουργίας THREAD { } AS και τέσσερις επιμέρους, όπως INTERVAL, HOLD, ERASE, RESTART. Τώρα έχει και την THREAD SET για μια σειρά στατικών μεταβλητών και την EXECUTE με την οποία από άλλο νήμα μπορούμε να εκτελέσουμε μια εντολή άμεσα στο νήμα που θέλουμε!

Παρακάτω είναι δυο προγράμματα στα αγγλικά (στα προχωρημένα θέματα προτιμώ τα αγγλικά, γιατί έχουν παραπονεθεί παλιοί προγραμματιστές για τα Ελληνικά).

(επιπλέον αλλαγές που έχει η 140 είναι ένα 5% βελτίωση στη ταχύτητα)

Στο πρώτο πρόγραμμα με space bar ρίχνουμε τρία νούμερα στο νήμα. Με πάτημα πλήκτρου ποντικιού τερματίζει το πρόγραμμα. Φαίνονται πολλά στοιχεία, όπως η χρήση ρουτίνας, τα δυο αυτόματα νήματα, το AFTER { } και το MAIN.TASK { }.


\\ Example of using static variable in Thread
\\ and new command "Execute" for inject commands..to Thread
\\ Here we place data in Thread's stack for values
\\ and also we place a specific assignment (ok=I>2000)
\\ we can mix plans
Thread.plan Sequential

OK=False : I=10
After 1000 {
      Print "Hello There - this is one time running Thread"
}
\\ but not this....
Thread {
      If Not Empty Then Read mmm : Print ">>>>>>>>>>>", mmm
      Thread set I=100 ' this set once If no I found as static in Thread
      printme(I)
      I++
} as k interval 10


\\ this is a Thread too (we can use non Thread like Every 80 { ]


Main.Task 80 {
      If mouse=1 Then Exit
      Print "wait", I ' this is module's I
      If Inkey$=" " Then {
            \\ Data command do a merge in the bottom of thread stack
            \\ so is  FIFO mechanism
            \\ Use Push command to make it LIFO
             Thread K Execute Data I**2, I**1.5, I**.5
      }
      ' here Execute run on K Thread so I is a static variable in K Thread
      ' but OK is module's variable
      Thread K Execute OK=I>2000
      If OK Then Thread k Erase : Exit
}
\\ for all conditions is better to Erase all threads
\\ but Main.Task (is a Thread also) erase modules threads
Threads Erase
\\ when interpreter found Sub stop normal the prorgam
Sub printme(X)
      Print X
End Sub



Το δεύτερο πρόγραμμα φτιάχνει πέντε πανομοιότυπα νήματα, τα οποία καλούν ένα τμήμα όπου αρχικά τροφοδοτούν δυο στατικές μεταβλητές του. Κάθε νήμα θα δώσει άλλα στοιχεία, και εν τέλει το τμήμα φαίνεται να "υπάρχει" πέντε φορές! Έχω χρησιμοποιήσει σχέδιο νημάτων ταυτόχρονο (έτσι το λέω στη Μ2000, στο προηγούμενο παράδειγμα έχω χρησιμοποιήσει το διαδοχικό, δηλαδή τερματίζει το κάθε νήμα και μετά ξεκινάει το άλλο - σε χρονοβόρες διαδικασίες όπως π.χ. να περιμένουμε εισαγωγή χαρακτήρων σε ένα νήμα...συνεχίζουν τα άλλα νήματα να τρέχουν)
Εδώ το If  Then Else δεν μπορεί να "πετύχει" στο σπάσιμο και έτσι το έχουμε σε μπλοκ, επειδή τα μπλοκ έχει εντολές που θα τρέξουν μαζί όπως και να έχει το πράγμα!
Η once είναι στατική για κάθε νήμα. Και σε κάθε νήμα θα τρέξει η look με άλλες στατικές!
Στην Look η εντολή Static θα δει αν υπάρχουν οι μεταβλητές. Αν υπάρχουν δεν εκτελεί το =Number (το οποίο διαβάζει από σωρό τιμών αυτά που βάζει το νήμα).
Μετά το Thread {  } As variable μπορούν να μπουν μια από τις δύο Interval ή Execute. Αν δεν μπει το Interval (έστω και μετά) δεν ξεκινάει το νήμα.

Σε αργούς υπολογιστές το  concurrent (ταυτόχρονο) εκτελείται με περίεργο τρόπο (εκτελεί τα πέντε νήματα και σαν να ξεκουράζεται, και μετά συνεχίζει...). Δοκιμάστε και με τα δύο συστήματα, βγάλτε το rem από το ένα και βάλτε το στο άλλο trhead.plan (Σχέδιο.νημάτων)



rem thread.plan sequential
thread.plan concurrent \\ in concurrent plan each thread run one command and switch to other
\\ with respect to time interval (each thread run in a minimum interval)
\\ but this can be extent.
\\ All threads need time to run
\\ here we choose only to set two wait commands
module look {
      ' static set once
      ' each thread call module look
      ' from own process, so we have 5 set of static variables
      Static L=number, b=number
      L++
      Print format$( "look {0} from {1}", L,b)
}
For I=1 to 5 ' just change 5 to 10 and we get 10 threads
      thread { ' set one time      
      thread set once=true \\ if then else in a block because we choose concurrent plan}
      {if once then { look klm, bb : once=false } else look}
      Print m, bb, b$, klm
      m++
      } as b execute thread set m=10**i, bb=b, b$="George", klm=random(1000)
      Thread b interval 100 ' set interval to 30 to see how fast screen change     
Next I
Wait 2000
thread b execute b$ = "Hello There " +b$
thread b-3 execute b$ = "Good Bye " +b$
Wait 2000
list   ' only I and B are modules variables
threads erase

Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.