mboost-dp1
Vækkeur program..
- Forside
- ⟨
- Forum
- ⟨
- Programmering
Start programmet, set time, spørg hvad klokken er. Du ved nu hvor lang tid der er tilbage. Dræb tråden eller whatever.
wait(tid_tilbage)
alarm()
Optional:Spørg igen hvad klokken er når halvdelen er tiden er tilbage, rinse repeat indtil alarmen skal ringe.
Note: Jeg har ingen ide om det er den bedste, korrekte eller mest effektive måde at gøre det på. Det var blot en ide.
wait(tid_tilbage)
alarm()
Optional:Spørg igen hvad klokken er når halvdelen er tiden er tilbage, rinse repeat indtil alarmen skal ringe.
Note: Jeg har ingen ide om det er den bedste, korrekte eller mest effektive måde at gøre det på. Det var blot en ide.
Du skal i hvert fald ikke lave en while-løkke, som konstant tjekker klokken. Det giver max. load på din CPU. :-)
Så vidt jeg husker kan du sætte Windows til at sende nogle timer Windows Messages, så sæt Windows til at sende en message f.eks. hvert sekund, og tjek kun hver gang du modtager en sådan en timer message. Så skulle CPU-forbruget gerne holde sig på praktisk talt 0%.
Så vidt jeg husker kan du sætte Windows til at sende nogle timer Windows Messages, så sæt Windows til at sende en message f.eks. hvert sekund, og tjek kun hver gang du modtager en sådan en timer message. Så skulle CPU-forbruget gerne holde sig på praktisk talt 0%.
Du kommer til at skulle lave et kompromis mellem ressourceforbrug og præcision.
Det er nemt at checke hvad klokken er og beregne hvor lang tid der er til alarmen skal gå af. Det største problem er hvad der sker hvis uret bliver stillet eller systemet bliver lagt i dvale i mellemtiden.
I hvert af de to nævnte tilfælde er der to muligheder for hvad et program kan ønske. Det giver fire kombinationsmuligheder. Jeg har ikke set nogen API som giver mulighed for frit at vælge mellem alle mulighederne. Du må selv undersøge hvad Windows API tillader.
En mulighed er at sætte en øvre grænse for hvor længe dit program sover, og så hver gang det vækkes op undersøge om der skal soves længere. På den måde kan du selv korrigere hvis der sker ændringer pga. af dvale eller ændringer af tiden. Længden af den periode dit program sover afgør hvor stor unøjagtigheden bliver.
Hvis du f.eks. højst sover et minut ad gangen, så er der højst et minuts fejl, og kun hvis der skete noget det sidste minut før tiden. Så længe der hverken sker ændringer af tiden eller dvale kan du ramme det rigtige tidspunkt med få ms. præcision uanset hvor længe processen sover.
At vågne op hvert minut koster dog nogle ressourcer. Der skal ikke bruges ret meget CPU tid på at vågne op og checke om der skal ske noget nu, men hvis alle processer gør det, så løber det jo op. Samtidigt vil du tvinge nogle hukommelsessider til at blive i fysisk hukommelse. Hvis processen blot sov hele perioden ud kunne den swappes ud så den hukommelse kunne bruges til noget mere brugbart i mellemtiden. Jeg ved ikke præcist hvor meget hukommelse det ville komme til at koste, mit gæt er i størrelsesordenen omkring 20KB per process der gør det.
Så er der spørgsmålet om hvorvidt du vil acceptere at der kommer til at gå nogle få sekunder med at swappe din process ind når den vækkes. Sandsynligvis er du ligeglad med om der måske skal bruges 5s på at swappe det hele ind.
Hvis du bekymrer dig om det kan du lade processen vågne et minut tidligere og sikre sig at alt er swappet ind. Hvad Windows APIen for den slags hedder ved jeg ikke. I posix ville man bruge madvise kaldet.
Personligt ville jeg synes det var overkill da du sikkert ikke bekymrer dig om et sekund fra eller til. Og det vil alligevel kun være præcist hvis computerens ur er stillet med NTP.
Det næste spørgsmål er hvorvidt du vil have at dit program skal have en brugerflade åben som kan tilgås mens programmet sover. Hvis du vil lave den slags skal du også håndtere events fra brugerfladen. Nogle systemer checker løbende om programmet svarer på events så det kan indikere hvis processen hænger. Hvis Windows gør det samme, så kan det gå ud over forsøg på at spare resourcer ved ikke at gøre noget hele tiden.
At på en gang sove og samtidigt skulle håndtere events hænger ikke helt godt sammen designmæssigt og kan nemt resultere i et klodset design. En god API ville tillade dig at du kunne modtage en event der fortæller dig når et bestemt tidspunkt er nået. Hvis du kan få både brugerinput og oplysning om alarmtidspunkt gennem samme event API ville det gøre koden pænere.
Igen ved jeg ikke hvordan det præcist gøres i Windows, så jeg vil i stedet nævne nogen af de kald jeg kender i posix, så må du selv finde Windows ækvivalenten. I posix kan man bruge select til at vente på input på et antal file descriptors med et timeout således at processen vækkes efter et bestemt interval, hvis der intet input kommer. Events fra brugeren kommer over file descriptors, men det er dog for low level til at man har lyst til at udvikle sine applikationer ved at kommunikere direkte med grafiksystemet over file descriptors. I stedet skal man bruge nogle libraries på et højere niveau. Her er udfordringen at på en gang vente på events fra forskellige libraries og nogle man måske får direkte fra OS. Det er ret tricky at designe en event API som fungerer pænt sammen med andre event APIer man ikke kender til.
Et stykke hen ad vejen kunne man undgå begrænsninger i event APIerne ved at have flere tråde til at vente på forskellige events. Men det bliver nemt kompliceret. I samme øjeblik man begynder at skrive multitrådet kode bliver alting lidt vanskeligere. Men i nogle tilfælde er det det værd.
Multitrådet programmering er dog ikke en magisk løsning på alting. Hvad nu hvis en tråd sover og en anden tråd finder ud af at den sovende tråd ikke skal sove så længe som først antaget? Hvis APIen som minimum tillader at en tråd kan blive vækket af en anden tråd kan det dog stadig løses.
Jeg vil prøve at beskrive det med et eksempel. Lad os sige at brugeren har set en alarm om 9 timer. Du kunne have en tråd som er lagt til at sove i 9 timer. Så laver brugeren alarmen om til om 8 timer. Hvordan kan GUI tråden så få timer tråden til at vågne om 8 timer, når den allerede har lagt sig til at sove i 9 timer?
Hvis APIen tillader det kunne timer tråden i stedet vælge at vente på en event fra en anden tråd med et timeout på 9 timer. Havde brugeren ikke lavet alarmen om var timer tråden blevet vækket på det rette tidspunkt efter 9 timers timeout. Idet brugeren laver en ændring modtager tråden en besked fra GUI tråden således at den vågner med det samme og ikke skal vente på timeout. Når timer tråden vågner skal den selvfølgelig starte med at undersøge hvorfor den blev vækket.
Hvis du gerne vil håndtere at brugeren kan indstille mere en enkelt alarm ad gangen bør du stadig kun bruge en tråd til timing. Den sover så blot indtil den første alarm. Den simpleste datastruktur til formålet er nok en linket liste sorteret efter tidspunkt. Den første alarm står i hovedet, den sidste alarm står i halen. Ulempen er at det tager lineær tid at opdatere strukturen. Hvis du vil gøre strukturen effektiv med tusindvis af alarmer, så får du i stedet brug for en prioritetskø implementeret vha. en heap.
Om du vælger et enkelttrådet event drevet design eller et multitrådet design (som selvfølgelig stadig vil skulle håndtere events i en eller anden form) er helt op til dig (og de APIer du har til rådighed).
Det lød som om det for dig primært går ud på at lære noget, så jeg har prøvet at nævne alle de ting du kan tage med i dine overvejelser. Nogle af tingene er du måske ikke interesseret i at kaste dig ud i med det samme.
Det er nemt at checke hvad klokken er og beregne hvor lang tid der er til alarmen skal gå af. Det største problem er hvad der sker hvis uret bliver stillet eller systemet bliver lagt i dvale i mellemtiden.
I hvert af de to nævnte tilfælde er der to muligheder for hvad et program kan ønske. Det giver fire kombinationsmuligheder. Jeg har ikke set nogen API som giver mulighed for frit at vælge mellem alle mulighederne. Du må selv undersøge hvad Windows API tillader.
En mulighed er at sætte en øvre grænse for hvor længe dit program sover, og så hver gang det vækkes op undersøge om der skal soves længere. På den måde kan du selv korrigere hvis der sker ændringer pga. af dvale eller ændringer af tiden. Længden af den periode dit program sover afgør hvor stor unøjagtigheden bliver.
Hvis du f.eks. højst sover et minut ad gangen, så er der højst et minuts fejl, og kun hvis der skete noget det sidste minut før tiden. Så længe der hverken sker ændringer af tiden eller dvale kan du ramme det rigtige tidspunkt med få ms. præcision uanset hvor længe processen sover.
At vågne op hvert minut koster dog nogle ressourcer. Der skal ikke bruges ret meget CPU tid på at vågne op og checke om der skal ske noget nu, men hvis alle processer gør det, så løber det jo op. Samtidigt vil du tvinge nogle hukommelsessider til at blive i fysisk hukommelse. Hvis processen blot sov hele perioden ud kunne den swappes ud så den hukommelse kunne bruges til noget mere brugbart i mellemtiden. Jeg ved ikke præcist hvor meget hukommelse det ville komme til at koste, mit gæt er i størrelsesordenen omkring 20KB per process der gør det.
Så er der spørgsmålet om hvorvidt du vil acceptere at der kommer til at gå nogle få sekunder med at swappe din process ind når den vækkes. Sandsynligvis er du ligeglad med om der måske skal bruges 5s på at swappe det hele ind.
Hvis du bekymrer dig om det kan du lade processen vågne et minut tidligere og sikre sig at alt er swappet ind. Hvad Windows APIen for den slags hedder ved jeg ikke. I posix ville man bruge madvise kaldet.
Personligt ville jeg synes det var overkill da du sikkert ikke bekymrer dig om et sekund fra eller til. Og det vil alligevel kun være præcist hvis computerens ur er stillet med NTP.
Det næste spørgsmål er hvorvidt du vil have at dit program skal have en brugerflade åben som kan tilgås mens programmet sover. Hvis du vil lave den slags skal du også håndtere events fra brugerfladen. Nogle systemer checker løbende om programmet svarer på events så det kan indikere hvis processen hænger. Hvis Windows gør det samme, så kan det gå ud over forsøg på at spare resourcer ved ikke at gøre noget hele tiden.
At på en gang sove og samtidigt skulle håndtere events hænger ikke helt godt sammen designmæssigt og kan nemt resultere i et klodset design. En god API ville tillade dig at du kunne modtage en event der fortæller dig når et bestemt tidspunkt er nået. Hvis du kan få både brugerinput og oplysning om alarmtidspunkt gennem samme event API ville det gøre koden pænere.
Igen ved jeg ikke hvordan det præcist gøres i Windows, så jeg vil i stedet nævne nogen af de kald jeg kender i posix, så må du selv finde Windows ækvivalenten. I posix kan man bruge select til at vente på input på et antal file descriptors med et timeout således at processen vækkes efter et bestemt interval, hvis der intet input kommer. Events fra brugeren kommer over file descriptors, men det er dog for low level til at man har lyst til at udvikle sine applikationer ved at kommunikere direkte med grafiksystemet over file descriptors. I stedet skal man bruge nogle libraries på et højere niveau. Her er udfordringen at på en gang vente på events fra forskellige libraries og nogle man måske får direkte fra OS. Det er ret tricky at designe en event API som fungerer pænt sammen med andre event APIer man ikke kender til.
Et stykke hen ad vejen kunne man undgå begrænsninger i event APIerne ved at have flere tråde til at vente på forskellige events. Men det bliver nemt kompliceret. I samme øjeblik man begynder at skrive multitrådet kode bliver alting lidt vanskeligere. Men i nogle tilfælde er det det værd.
Multitrådet programmering er dog ikke en magisk løsning på alting. Hvad nu hvis en tråd sover og en anden tråd finder ud af at den sovende tråd ikke skal sove så længe som først antaget? Hvis APIen som minimum tillader at en tråd kan blive vækket af en anden tråd kan det dog stadig løses.
Jeg vil prøve at beskrive det med et eksempel. Lad os sige at brugeren har set en alarm om 9 timer. Du kunne have en tråd som er lagt til at sove i 9 timer. Så laver brugeren alarmen om til om 8 timer. Hvordan kan GUI tråden så få timer tråden til at vågne om 8 timer, når den allerede har lagt sig til at sove i 9 timer?
Hvis APIen tillader det kunne timer tråden i stedet vælge at vente på en event fra en anden tråd med et timeout på 9 timer. Havde brugeren ikke lavet alarmen om var timer tråden blevet vækket på det rette tidspunkt efter 9 timers timeout. Idet brugeren laver en ændring modtager tråden en besked fra GUI tråden således at den vågner med det samme og ikke skal vente på timeout. Når timer tråden vågner skal den selvfølgelig starte med at undersøge hvorfor den blev vækket.
Hvis du gerne vil håndtere at brugeren kan indstille mere en enkelt alarm ad gangen bør du stadig kun bruge en tråd til timing. Den sover så blot indtil den første alarm. Den simpleste datastruktur til formålet er nok en linket liste sorteret efter tidspunkt. Den første alarm står i hovedet, den sidste alarm står i halen. Ulempen er at det tager lineær tid at opdatere strukturen. Hvis du vil gøre strukturen effektiv med tusindvis af alarmer, så får du i stedet brug for en prioritetskø implementeret vha. en heap.
Om du vælger et enkelttrådet event drevet design eller et multitrådet design (som selvfølgelig stadig vil skulle håndtere events i en eller anden form) er helt op til dig (og de APIer du har til rådighed).
Det lød som om det for dig primært går ud på at lære noget, så jeg har prøvet at nævne alle de ting du kan tage med i dine overvejelser. Nogle af tingene er du måske ikke interesseret i at kaste dig ud i med det samme.
Du mener ligesom når man outsourcer, og bruger mere tid på at skrive specifikationen som Inderne skal bruge, end det tager at kode programmet i første omgang?-)fjols (8) skrev:Toppen af nørderi må være når man skriver et indlæg om hvordan man koder et program der er længere end selve koden ville være ;)
Gå til top
Opret dig som bruger i dag
Det er gratis, og du binder dig ikke til noget.
Når du er oprettet som bruger, får du adgang til en lang række af sidens andre muligheder, såsom at udforme siden efter eget ønske og deltage i diskussionerne.