torsdag 23. september 2010 Diverse prosjekter Ping Ring Basic Assembly PHP Haskell Samtidighet
Dette er del 9 i artikkelserien Ping Ring hvor jeg implementerer et og samme program i et utall ulike programmeringsspråk - for å se om det er noe å lære gjennom å gjøre det. Introduksjonen kan du lese her.
Samtidig som jeg startet denne artikkelserien utfordret jeg også folkene på Norsk Freakforum til å implementere den samme oppgaven i språk som jeg selv ikke behersket. Og flere var villige til å bidra. Denne episoden av Ping Ring tar for seg disse implementasjonene.
Programmeringsdelen av Freakforum er et sted hvor man kan gjøre alt fra å diskutere hvorvidt Python eller VB.NET er det beste språket å starte med for ferske utviklere (og det er i alle fall ikke Python), til å løse skoleoppgavene til folk. Jeg tar turen innom av og til, for det hender faktisk det dukker opp interessante ting. Det er mange der som ønsker å lære mer programmering, og da kan det være givende å hjelpe til litt innimellom.
Det første bidraget jeg fikk var i PureBasic, en komersiell BASIC-variant som er tilgjengelig på Windows, Linux, MaC OS X og faktisk også Amiga. Løsningen ble laget av Kråkelefse, og er tilgjengelig fra min github repo. Her er et utdrag:
Størrelsesmessig (kodelinjer og bytes) er det en av de lengre implementasjonene, omtrent på nivå med C# og Erlang. Men BASIC skal jo være enkelt å forstå, og løsningen er ganske ryddig og fin - absolutt mye bedre enn Erlang-varianten på det området.
Neste bidrag er noe ganske anderledes, nemlig en implementasjon i FASM (flat assembler) for x86-64, skrevet av Akhkharu. Det begynte med en versjon på 324 linjer, men etter å ha laget noen "litt fikse macroer" fikk han ned antallet til 199. Her følger et lite utdrag som kanskje gir deg følelsen av hvordan det arter seg å skrive assembler-kode. Hele kilden finner du her.
Akhkharu postet denne koden med den passende kommentaren: "… og det var nok masochisme for i år."
Og så til et bidrag jeg ikke trodde skulle komme. |d13m0b har gjort et forsøk på å implementere en Ping Ring i PHP. Han advarer om at koden kan inneholde feil, for den ble skrevet på vorspiel. Men den illustrerer uansett hvordan en dyktig utvikler kan ta et verktøy beregnet for en bestemt oppgave (som å slå inn spiker), og gjøre noe helt annet med den (som å pusse tennene).
Utvikleren forklarer:
Når man skal skrive dette programmet i php oppstår det et par små problemer; PHP har ikke threading. I alle fall ikke threading i den forstand man forbinder med "normale" språk.
Det man er nødt til da er å forke, og det som skjer er at prosessen spawner en ny prosess (som er nøyaktig samme scriptet), og man må sjekke PID for å bestemme hva som er child eller parent og deretter gjøre handling ut i fra dette. Igjennom php kan man aksessere kallet med pcntl_fork. Slik jeg har satt det opp vil det lages 3 prosesser. En for PingAlertProcesser og en for PingListener, og det "opprinnelige" scriptet er parent og holder øye med barna om de dør eller ikke.
Så man har fått "threading" av veien, og så støter man imidlertid på en aldri så liten utfordring til. Hvordan får man delt variabler mellom scriptene? Man kan selvfølgelig serialisere og dumpe til en fil som alle scriptene har tilgang til, men dette er ikke akkurat noen optimal løsning.
Heldigvis har php noe matnyttig man kan bruke; Semaphore. Dette er en wrapper til SysV sine IPC-kall. Vi sitter altså med en modul som kan håndtere minnet mellom uavhengige prosesser (getLastPing og setLastPing)."
|d13m0b har på en måte nesten gjennoppfunnet Erlang-løsningen i PHP :) Den fullstendige kildekoden er på 217 linjer, og er tilgjengelig her. Her er en smakebit fra semafor-koden:
Bidragsyteren avslutter med følgende kommentar om å implementere Ping Ring eller lignende slik han har gjort:
"Ikke gjør det i php, og ikke gjør det i fylla."
Jeg fikk også se en implementasjon i Haskell, og den er tilgjengelig i sin helhet her. Koden inneholder endel unicode, men jeg gjør et forsøk på å rendrere et lite utdrag (krysser fingrene):
Akhkharu, som leverte denne løsningen også, innrømmet at han ikke så noen fordel med å implementere Ping Ring i Haskell. Koden er ifølge tallene like lite kompakt som Erlang-versjonen.
I tillegg til de implementasjonene dere har fått sett smakebiter av her inneholder Ping Ring contrib-repositorien på Github også tre ulike Python-implementasjoner. Ta en titt, og se om du blir inspirert til å implementere din egen ring i det språket du liker best. Eller kanskje du skal prøve deg på et språk du aldri har gjort noe i før? Hvorfor ikke?!!
Tidligere i serien: Introduksjon | C# | Ruby | Boo | Erlang | Clojure | Clojure m/Agenter | Python.
Kildekoden fra denne blogposten er tilgjengelig på Github. Der står du fritt til å forgrene løsningen og gjøre egne modifikasjoner om du ønsker det (for å illustrere et poeng eller lignende). Som alt annet på bloggen er koden lisensiert under Creative Commons.