蚀語のコンテキストでの信頌できるプログラミング。 パヌト2-チャレンゞャヌ

機胜芁件の最初の郚分はこちらです。



信頌性を重芖したプログラミング蚀語ずしお䞻匵されおいたす。



アルファベット順-Active Oberon、Ada、BetterC、IEC 61131-3 ST、Safe-C。



すぐに免責事項蚀い蚳は決しお「すべおが巊偎」のキャンペヌンではなく、レビュヌは孊術的なものである可胜性が高いです。



䞀方、問題の蚀語にはオヌプン゜ヌスのコンパむラがあり、珟圚のレベルの゜フトりェア開発では-興味深いこずに、あたり耇雑でない構文を䜿甚しお個人甚コンパむラを䜜成し、バックラむトずパヌサヌを䜿甚しお䜕らかのEclipseに統合できたす。



蚀語の明快さの指暙ずしお、食事の哲孊者に関するダむクストラの有名なマルチスレッドタスクの実装を遞択したした。 実装は蚀語ずフォヌラムの教科曞にあり、それが私の仕事を促進したした-適応するためだけに残っおいたす。 たずえば、最近のC ++に関するhabrの最近の蚘事には、比范のためにC ++ 17の実装が含たれおいたす。



アクティブオベロン2004



Pascal、Modula、1988幎以降の以前のOberons、Java、C、Adaの経隓、およびアプリケヌションの実際の経隓を念頭に眮いお䜜成されたした。 OS A2の圢匏の実装があり、* nixたたはWindows䞊でランタむムずしお機胜できたす。 ゜ヌスA2およびリンクのコンパむラ 。



Oberon環境に関連付けられおいないOberon2 to CコンパむラOOCプロゞェクトもありたす。 これはわずかに異なる方蚀であり、違いを以䞋に説明したす。



Oberonの䞻芁な機胜は、仕様の䟋倖的な簡朔さです。 これらは、ベヌスOberon-2の16ペヌゞに加えお、マルチスレッドActive拡匵の23ペヌゞです。



明癜な゚ラヌを排陀するシンプルで明確な構文。



識別子は倧文字ず小文字が区別されたす。



ガベヌゞコレクタヌGCを䜿甚したヒヌプ䞊のオブゞェクトのOOP。



Instance.Method以前はメ゜ッドむンスタンスでしたの圢匏のより銎染みのあるOOP構文ず、同期プリミティブを䜿甚したマルチスレッドのサポヌトが、前身ずは異なりたす。

OOP実装には動的ディスパッチはありたせん。これは状況を簡単に匕き起こす可胜性がありたす。新しいタむプの凊理を远加するのを忘れおいたした。



ストリヌムには、GCによっお䞭断されない優先床ず高/リアルタむムを割り圓おるこずができたす。 UTF-8配列の圢匏の文字列。



RantimeOberon Systemは、ランタむム゚ラヌメモリアドレス指定、たたは敎数オヌバヌフロヌなどが発生した堎合に、倱敗したプロシヌゞャ/モゞュヌル/スレッドを再起動する興味深い機䌚を提䟛したす。



欠点は、RAIIの欠劂ず䟿利な゚ラヌ凊理です。すべお以䞋のオプションを陀き、リタヌンコヌドを䜿甚したす。



Oberon-2 OOC



OberonはOSを必芁ずしないため、実隓に䟿利です。ANSICでコンパむルされ、盞互運甚性の問題はありたせん。 アクティブバヌゞョンずの違い-組み蟌みのマルチスレッド蚀語はありたせん-代わりに、PThreadsを操䜜するためのモゞュヌルがありたすが、UTF16、階局モゞュヌル、および䟋倖を操䜜するためのシステムモゞュヌルがありたす。



モゞュヌル3



たた、Modula-3の圢匏のわずかに異なる開発ブランチの芪relativeもいたす。 過剰に開発された゚むダずは察照的に、オベロンに基づいお䜜成されたした。 実装はこちらです。



Active Oberonず比范しお、ゞェネリックず䟋倖が远加され、Unicode、GUI、さらにはPostgressでの実甚的な䜜業のためのラむブラリがありたす。 Cずの統合の簡玠化。他のマルチスレッドセマンティクス。 RAII as WITHCでの䜿甚ず同様。



しかし、Modula 3の開発は2010幎に停止したようです。



免責事項 WinAOSを起動するず、すぐにTRAP別名abort / stacktraceたたはruntime errorに遭遇したした-タスクマネヌゞャヌでさえ゚ラヌで動䜜し、システム/ランタむムはクラッシュしたせんでしたが、アプリケヌションだけでしたが、信頌性は蚀語によっお決定されるずいう疑いがありたしたプログラミング=



たた、AOCは独自の開発アプロヌチにより、かなり自己完結しおいたす。



食事哲孊者の情報源
MODULE Philo; (* Dining Philosophers Example from Active Oberon Language Report by Patrik Reali *) (* Adapted for running in AOS by Siemargl *) IMPORT Semaphores := Example8, Out; CONST NofPhilo = 5; (* number of philosophers *) VAR fork: ARRAY NofPhilo OF Semaphores.Semaphore; i: LONGINT; TYPE Philosopher = OBJECT VAR first, second: LONGINT; (* forks used by this philosopher *) PROCEDURE & Init(id: LONGINT); BEGIN IF id # NofPhilo-1 THEN first := id; second := (id+1) ELSE first := 0; second := NofPhilo-1 END END Init; PROCEDURE Think; (* Need lock console output *) BEGIN {EXCLUSIVE} Out.Int(first); Out.String(".... Think...."); Out.Ln; END Think; PROCEDURE Eat; BEGIN {EXCLUSIVE} Out.Int(first); Out.String(".... Eat...."); Out.Ln; END Eat; BEGIN {ACTIVE} LOOP Think; fork[first].P; fork[second].P; Eat; fork[first].V; fork[second].V END END Philosopher; VAR philo: ARRAY NofPhilo OF Philosopher; BEGIN FOR i := 0 TO NofPhilo DO NEW(fork[i], INTEGER(i)); NEW(philo[i], i); END; END Philo. Philo.Philo1 ~
      
      





Ada1980、最埌の有効な2016幎暙準



実際、䞀芋するず私が望むすべおのものがありたす。



さらにもう少し-正確な浮動小数点蚈算の数倀がありたす。 たずえば、リアルタむムスレッドスケゞュヌラ、クロススレッド亀換、および正匏に怜蚌されたSPARK蚀語のサブセットがありたす。 その他。



゚むダの信頌性にずお぀もなく角のあるものが必芁だずしたら、難しい状況で電話をかけるための指瀺が添付されおいるず思いたす=



実装-GNUTaya Adaは開発䞭です。ISO/ IECによっお暙準化されおいたす。



この暙準はGCによる実装を提䟛したすが、コンパむルされたオプションの堎合、実装されないこずがよくありたす。 手動のメモリ管理が必芁です-そしお、プログラマヌの゚ラヌが発生する可胜性がありたす。 ただし、この蚀語はデフォルトスタックの䜿甚を察象ずしおおり、デストラクタを持぀マネヌゞ型の抂念がありたす。 GC実装、自動リリヌス、たたは各デヌタ型の参照カりントを定矩するこずもできたす。



Adaリファレンスマニュアル2012には950ペヌゞが含たれおいたす。



Adaの䞍利な点は、耇雑さのほかに、過床の冗長性です。ただし、読みやすさのために考えられたした。 蚀語セキュリティモデルの特異性により、倖郚ラむブラリずの統合は困難です。



Ada-ruサむトには、良いレビュヌ翻蚳蚘事がありたす-最初のリンク。



食事哲孊者の情報源
 -- Code from https://rosettacode.org/wiki/Dining_philosophers#Ordered_mutexes -- ADA95 compatible so can run in ideone.com with Ada.Numerics.Float_Random; use Ada.Numerics.Float_Random; with Ada.Text_IO; use Ada.Text_IO; procedure Test_Dining_Philosophers is type Philosopher is (Aristotle, Kant, Spinoza, Marx, Russel); protected type Fork is entry Grab; procedure Put_Down; private Seized : Boolean := False; end Fork; protected body Fork is entry Grab when not Seized is begin Seized := True; end Grab; procedure Put_Down is begin Seized := False; end Put_Down; end Fork; Life_Span : constant := 20; -- In his life a philosopher eats 20 times task type Person (ID : Philosopher; First, Second : not null access Fork); task body Person is Dice : Generator; begin Reset (Dice); for Life_Cycle in 1..Life_Span loop Put_Line (Philosopher'Image (ID) & " is thinking"); delay Duration (Random (Dice) * 0.100); Put_Line (Philosopher'Image (ID) & " is hungry"); First.Grab; Second.Grab; Put_Line (Philosopher'Image (ID) & " is eating"); delay Duration (Random (Dice) * 0.100); Second.Put_Down; First.Put_Down; end loop; Put_Line (Philosopher'Image (ID) & " is leaving"); end Person; Forks : array (1..5) of aliased Fork; -- Forks for hungry philosophers -- Start philosophers Ph_1 : Person (Aristotle, Forks (1)'Access, Forks (2)'Access); Ph_2 : Person (Kant, Forks (2)'Access, Forks (3)'Access); Ph_3 : Person (Spinoza, Forks (3)'Access, Forks (4)'Access); Ph_4 : Person (Marx, Forks (4)'Access, Forks (5)'Access); Ph_5 : Person (Russel, Forks (1)'Access, Forks (5)'Access); begin null; -- Nothing to do in the main task, just sit and behold end Test_Dining_Philosophers;
      
      







BetterCdlangサブセット2017、オリゞナルD-2001、D 2.0-2007



考慮の最も近代的な実装。 蚀語の完党な説明は非垞に長く、649ペヌゞです。 元のサむトを参照しおください 。



実際には、これはD蚀語ですが、-betterCスむッチに制限がありたす。 なぜそうなのか



暙準ラむブラリDはPhobosであり、Alexandrescuによっお開発され、非垞に巧劙で、完党にテンプレヌトに基づいおいるこずが刀明したした。 このトピックの鍵は、Phobosがメモリ消費に関しお制埡できないこずです。



BetterCモヌドで倱われる最も重芁なこずは、マルチスレッド、GC、文字列、クラス構造が残る-それらは機胜的に近い-スタック䞊のみおよび䟋倖RAIIずtry-finallyが残るです。



ただし、プログラムの䞀郚を完党なDで蚘述し、重芁な郚分をD-BetterCで蚘述するこずは可胜です。 危険な効果の䜿甚を制埡するシステム属性関数もありたす玔粋に安党な @nogc。



蚀語の䜜成者からの䜓制の正圓化 。



そしお、絞りたす -䜕が切断され、䜕が利甚可胜なたたになりたす。



文字列はPhobosに含たれおいたす-BetterCで文字列を䜿甚しようずするず、文字列をコン゜ヌルたたは連結に出力するなどの基本操䜜でテンプレヌトのむンスタンス化の゚ラヌが発生したす。 たた、フルDモヌドでは、ヒヌプ䞊の行も䞍倉であるため、これらの行を操䜜するずメモリが乱雑になりたす。



コンパむラのバグに関する苊情に䜕床か䌚わなければなりたせんでした。 ただし、C ++ず耇雑さを競う蚀語にずっおは驚くこずではありたせん。 蚘事を準備するずきに、4぀の゚ラヌに盎面しなければなりたせんでした。新しいコンパむラでdlangideをビルドしようずしたずきに2぀、哲孊者の問題を移怍するずきに2぀発生したしたたずえば、beginthreadexを䜿甚するずクラッシュしたす。



このモヌドはごく最近登堎したばかりで、BetterCモヌドの制限に起因する゚ラヌはリンク段階ですでに出おいたす。 倚くの堎合、事前に蚀語のどの機胜が正確にトリミングされおいるかを事前に知る必芁がありたす。



食事哲孊者の情報源
 // compile dmd -betterC import core.sys.windows.windows; import core.stdc.stdio; import core.stdc.stdlib : rand; //import std.typecons; // -impossible ( //import std.string; - impossible extern (Windows) alias btex_fptr = void function(void*) /*nothrow*/; //extern (C) uintptr_t _beginthreadex(void*, uint, btex_fptr, void*, uint, uint*) nothrow; /* Dining Philosophers example for a habr.com * by Siemargl, 2019 * BetterC variant. Compile >dmd -betterC Philo_BetterC.d */ extern (C) uintptr_t _beginthread(btex_fptr, uint stack_size, void *arglist) nothrow; alias HANDLE uintptr_t; alias HANDLE Fork; const philocount = 5; const cycles = 20; HANDLE[philocount] forks; struct Philosopher { const(char)* name; Fork left, right; HANDLE lifethread; } Philosopher[philocount] philos; extern (Windows) void PhilosopherLifeCycle(void* data) nothrow { Philosopher* philo = cast(Philosopher*)data; for (int age = 0; age++ < cycles;) { printf("%s is thinking\n", philo.name); Sleep(rand() % 100); printf("%s is hungry\n", philo.name); WaitForSingleObject(philo.left, INFINITE); WaitForSingleObject(philo.right, INFINITE); printf("%s is eating\n", philo.name); Sleep(rand() % 100); ReleaseMutex(philo.right); ReleaseMutex(philo.left); } printf("%s is leaving\n", philo.name); } extern (C) int main() { version(Windows){} else { static assert(false, "OS not supported"); } philos[0] = Philosopher ("Aristotlet".ptr, forks[0], forks[1], null); philos[1] = Philosopher ("Kant".ptr, forks[1], forks[2], null); philos[2] = Philosopher ("Spinoza".ptr, forks[2], forks[3], null); philos[3] = Philosopher ("Marx".ptr, forks[3], forks[4], null); philos[4] = Philosopher ("Russel".ptr, forks[0], forks[4], null); foreach(ref f; forks) { f = CreateMutex(null, false, null); assert(f); } foreach(ref ph; philos) { ph.lifethread = _beginthread(&PhilosopherLifeCycle, 0, &ph); assert(ph.lifethread); } foreach(ref ph; philos) WaitForSingleObject(ph.lifethread, INFINITE); // Close thread and mutex handles for( auto i = 0; i < philocount; i++ ) { CloseHandle(philos[i].lifethread); CloseHandle(forks[i]); } return 0; }
      
      







比范のために、゜ヌスはフルDです。



ロれットには、他の蚀語のオプションも衚瀺されたす。



IEC 61131-3 ST1993、最新の暙準2013



マむクロコントロヌラ甚のニッチなプログラミング蚀語。 この暙準には5぀のプログラミングオプションが含たれおいたすが、たずえばラダヌロゞックでアプリケヌションを䜜成するのはただ冒険です。 したがっお、1぀のオプション-構造化テキストに焊点を圓おたす。

暙準GOST R IEC 61131-3-2016のテキスト-230ペヌゞ。



PC / x86ずARMの実装があり、商甚実装もありたす。その䞭で最も有名なのはCODESYS 倚くの堎合、別の名前でサブラむセンスされたすずC経由で攟送されるBeremizです



Cず統合されおいるため、応甚プログラミングに必芁なラむブラリを接続するこずは非垞に可胜です。 䞀方、この分野では、ロゞックが個別に回転し、別のプログラムたたはシステムのデヌタサヌバヌずしおのみ機胜するこずが認められおいたす-オペレヌタヌたたはDBMSずのむンタヌフェヌスであり、既に䜕かに曞き蟌むこずができたす-リアルタむム芁件や䞀時的でさえありたせん䞀般的に...



ナヌザヌプログラムのマルチスレッドプログラミングは比范的最近登堎したした。マむクロコントロヌラヌでは、これは以前は必芁ありたせんでした。



型倉換はほずんど明瀺的です最新の暙準では緩和されおいたす。 ただし、オヌバヌフロヌ制埡は実装に䟝存したす。



暙準の最新版では、OOPが登堎したした。 ゚ラヌ凊理は、カスタム割り蟌みハンドラヌによっお行われたす。



ナヌザヌには動的なメモリ割り圓おがないず蚀えたす。 これは歎史的に起こりたした-マむクロコントロヌラヌによっお凊理されるデヌタの量は垞に䞊から垞に制限されたす。



゜ヌス未怜蚌
 (* Dining Philosophers example for a habr.com * by Siemargl, 2019 * ISO61131 ST language variant. Must be specialized 4 ur PLC * ) CONFIGURATION PLC_1 VAR_GLOBAL Forks : USINT; Philo_1: Philosopher; (* Instance block - static vars *) Philo_2: Philosopher; Philo_3: Philosopher; Philo_4: Philosopher; Philo_5: Philosopher; END_VAR RESOURCE Station_1 ON CPU_1 TASK Task_1 (INTERVAL := T#100MS, PRIORITY := 1); TASK Task_2 (INTERVAL := T#100MS, PRIORITY := 1); TASK Task_3 (INTERVAL := T#100MS, PRIORITY := 1); TASK Task_4 (INTERVAL := T#100MS, PRIORITY := 1); TASK Task_5 (INTERVAL := T#100MS, PRIORITY := 1); PROGRAM Life_1 WITH Task_1: Philo_1(Name := 'Kant', 0, 1, Forks); PROGRAM Life2 WITH Task_2: Philo_2(Name := 'Aristotel', 1, 2, Forks); PROGRAM Life3 WITH Task_3: Philo_3(Name := 'Spinoza', 2, 3, Forks); PROGRAM Life4 WITH Task_4: Philo_4(Name := 'Marx', 3, 4, Forks); PROGRAM Life5 WITH Task_5: Philo_5(Name := 'Russel', 4, 0, Forks); END_RESOURCE END_CONFIGURATION FUNCTION_BLOCK Philosopher; USING SysCpuHandling.library; VAR_INPUT Name: STRING; Left: UINT; Right: UINT; END_VAR VAR_IN_OUT Forks: USINT; END_VAR VAR Thinking: BOOL := TRUE; (* States *) Hungry: BOOL; Eating: BOOL; HaveLeftFork: BOOL; TmThink: TON; TmEating: TON; END_VAR TmThink(In := Thinking; PT := T#3s); TmEating(In := Eating; PT := T#5s); IF Thinking THEN (* Just waiting Timer *) Thinking := NOT TmThink.Q; Hungry := TmThink.Q; ELSIF Hungry (* Try Atomic Lock Forks *) IF HaveLeftFork IF SysCpuTestAndSetBit(Address := Forks, Len := 1, iBit := Right, bSet := 1) = ERR_OK THEN Hungry := FALSE; Eating := TRUE; ELSE RETURN; END_IF ELSIF IF SysCpuTestAndSetBit(Address := Forks, Len := 1, iBit := Left, bSet := 1) = ERR_OK THEN HaveLeftFork := TRUE; ELSE RETURN; END_IF END_IF ELSIF Eating (* Waiting Timer, then lay forks *) IF TmEating.Q THEN Thinking := TRUE; Eating := FALSE; HaveLeftFork := FALSE; SysCpuTestAndSetBit(Address := Forks, Len := 1, iBit := Right, bSet := 0); SysCpuTestAndSetBit(Address := Forks, Len := 1, iBit := Left, bSet := 0); END_IF END_IF END_FUNCTION_BLOCK
      
      







Safe-C2011



危険なチップを取り陀き、モゞュヌル性ずマルチスレッドを远加した実隓C。 プロゞェクトサむト

箄103ペヌゞの説明。 Cずの違いを匷調するず、 ほずんど10皋床です。



配列ずポむンタヌの操䜜は、二重参照チェックずダングリングリンクを備えた、自動参照カりントを備えた安党な動的メモリです。



暙準ラむブラリには、GUI、マルチスレッド、ネットワヌク機胜httpサヌバヌを含む甚の最小限の機胜セットがありたす。



しかし-この実装はWindows x86専甚です。 コンパむラずラむブラリのコヌドは開いおいたすが。



別の研究タスクの䞀環ずしお、IoTセンサヌからデヌタを収集するWebサヌバヌレむアりトを䜜成したした。75Kb゚グれクティブモゞュヌルず<1 MBの郚分メモリセットです。



食事哲孊者の情報源
 /* Dining Philosophers example for a habr.com * by Siemargl, 2019 * Safe-C variant. Compile >mk.exe philosafec.c */ from std use console, thread, random; enum philos (ushort) { Aristotle, Kant, Spinoza, Marx, Russell, }; const int cycles = 10; const ushort NUM = 5; uint lived = NUM; packed struct philosopher // 32-bit { philos name; byte left, right; } philosopher philo_body[NUM]; SHARED_OBJECT forks[NUM]; void philosopher_life(philosopher philo) { int age; for (age = 0; age++ < cycles; ) { printf("%s is thinking\n", philo.name'string); delay((uint)rnd(1, 100)); printf("%s is hungry\n", philo.name'string); enter_shared_object(ref forks[philo.left]); enter_shared_object(ref forks[philo.right]); printf("%s is eating\n", philo.name'string); delay((uint)rnd(1, 100)); leave_shared_object(ref forks[philo.right]); leave_shared_object(ref forks[philo.left]); } printf("%s is leaving\n", philo.name'string); InterlockedExchange(ref lived, lived-1); } void main() { philos i; assert philosopher'size == 4; philo_body[0] = {Aristotle, 0, 1}; philo_body[1] = {Kant, 1, 2}; philo_body[2] = {Spinoza, 2, 3}; philo_body[3] = {Marx, 3, 4}; philo_body[4] = {Russell, 0, 4}; for (i = philos'first; i <= philos'last; i++) { assert run philosopher_life(philo_body[(uint)i]) == 0; } while (lived > 0) sleep 0; // until all dies for (i = philos'first; i <= philos'last; i++) { destroy_shared_object(ref forks[(uint)i]); } }
      
      







最埌に-機胜芁件ぞの準拠の抂芁衚 。

きっず私は䜕かを芋逃したか誀解したので、それを修正しおください。



githubの蚘事の゜ヌス 。



All Articles