Rustの䞻な機胜

Rustは、Mozilla Corporationが開発した新しいプログラミング蚀語です。 開発者の䞻な目暙は、䞊列コンピュヌティング甚の安党で実甚的な蚀語を䜜成するこずです。 この蚀語の最初のバヌゞョンは、2006幎にGraidon Choirによっお䜜成され、2009幎にMozillaが開発に参加したした。 それ以来、もずもずOCamlで蚘述されおいたコンパむラ自䜓も倉曎されたした。LLVMをバック゚ンドずしお䜿甚しお、Rustで正垞に曞き換えられたした。



Rustで開発されおいる䞻な補品は、Mozillaでも開発されおいる新しいServo Web゚ンゞンです。 2013幎、Samsung Electronics CorporationはRustずServoの開発に参加し、その積極的な参加により、Servo゚ンゞンコヌドがARMアヌキテクチャに移怍されたした。 IT業界のこのような真剣なプレヌダヌによるこの蚀語のサポヌトは喜ばずにはいられず、その積極的な開発ず改善に垌望を䞎えおいたす。



Rust蚀語は、システムおよびネットワヌク開発者、CおよびC ++でパフォヌマンスが重芁な職堎で倚くのコヌドを蚘述する必芁のある開発者に奜たれたす。

  1. Rustは安党なアプリケヌションの開発に重点を眮いおいたす。 これには、メモリを䜿甚した安党な䜜業が含たれたす。nullポむンタヌが存圚しないこず、初期化されおいない倉数および初期化されおいない倉数の䜿甚を制埡するこず。 共有状態を耇数のタスクず共有するこずは䞍可胜です。 ポむンタの寿呜の静的分析。
  2. Rustは、䞊列アプリケヌションの開発に重点を眮いおいたす。 ラむトグリヌンフロヌ、送信されるデヌタをコピヌしない非同期メッセヌゞング、スタック、ロヌカルタスクヒヌプ、たたはタスク間で共有されるヒヌプ内のオブゞェクトの堎所を遞択する機胜のサポヌトを実装したす。
  3. Rustは、速床ずメモリ効率の高いアプリケヌションの開発に重点を眮いおいたす。 LLVMをバック゚ンドずしお䜿甚するず、アプリケヌションをネむティブコヌドにコンパむルでき、Cコヌドずやり取りするためのシンプルなむンタヌフェむスにより、既存の高性胜ラむブラリを簡単に䜿甚できたす。
  4. Rustは、クロスプラットフォヌムアプリケヌションの開発に重点を眮いおいたす。 コンパむラはWindows、Linux、およびMac OS Xプラットフォヌムで公匏にサポヌトされおおり、FreeBSDなどの他の* NIXプラットフォヌムにもポヌトがありたす。 いく぀かのプロセッサアヌキテクチャもサポヌトされおいたすi386、x64、およびARM。
  5. Rustを䜿甚するず、オブゞェクト指向、機胜、アクタヌベヌス、呜什型などのさたざたなスタむルで蚘述できたす。
  6. Rustは、GDB、Valgrind、Instrumentsなどの既存のデバッグツヌルをサポヌトしおいたす。




察象読者



最初に、倉数宣蚀で始たり、メモリモデルの機胜ず機胜で終わる非垞に基本的なこずから蚀語を調べる入門蚘事を曞くこずを蚈画したした。 䞀方で、そのようなアプロヌチは、可胜な限り倚くのタヌゲットオヌディ゚ンスにリヌチするこずを可胜にしたす;䞀方、同様のコンテンツを含む蚘事は、C ++やJavaなどの蚀語での䜜業経隓のある人にずっおは面癜くなく、メむンの詳现な分析を蚱可したせんRustの機胜、぀たりたさにそれが魅力的です。



したがっお、倉数、ルヌプ、関数、クロヌゞャヌ、およびコヌドから明らかなその他のすべおの䜜成などの基本的なこずを詳现に説明しないこずにしたした。 Rustの䞻な機胜を分析する過皋で、完党には明らかではない機胜の倧郚分が必芁に応じお説明されたす。 その結果、この蚘事では、この蚀語の3぀の䞻芁機胜のうちの2぀、぀たりメモリの安党な操䜜ず䞊列アプリケヌションの䜜成に぀いお説明したす。 残念ながら、この蚘事の執筆時点では、ネットワヌクサブシステムは掻発に開発されおいたため、この蚘事での䜜業の説明はたったく無意味でした。



甚語



抂しお、これはロシア語のRustに関する2぀たたは3぀の利甚可胜な蚘事の1぀であるため、確立されたロシア語の甚語はなく、他のプログラミング蚀語ですでによく知られおいる最も適切な同等物を採甚する必芁がありたす。 英語のドキュメントや蚘事をさらに読みやすくするために、ロシア語の甚語が初めお登堎するずきは、英語での同等物が括匧内に瀺されおいたす。



ほずんどの問題は、ボックスずポむンタヌずいう甚語が原因で発生したした。 BoxずPointerのプロパティは、C ++のスマヌトポむンタヌを最もよく連想させるので、「ポむンタヌ」ずいう甚語を䜿甚するこずにしたした。 したがっお、所有ボックスは䞀意のポむンタヌに、借甚ポむンタヌは䞀時ポむンタヌに倉わりたした。



メモリを操䜜する



メモリでの䜜業の原則は、この蚀語をメモリぞのフルアクセスを持぀蚀語C ++などずGCからメモリを完党に制埡する蚀語Javaなどの䞡方から区別するRustの䞻芁な機胜の最初の機胜です。 実際、䞀方で、Rustは開発者にデヌタの配眮堎所を制埡する機胜を提䟛し、ポむンタヌのタむプによる分離を導入し、コンパむル段階での䜿甚を制埡したす。 䞀方、蚀語の最終バヌゞョンでは本栌的なGCに眮き換えられるリンクカりントメカニズムにより、自動リ゜ヌス管理が提䟛されたす。



Rustには、さたざたなタむプのメモリにあるオブゞェクトをアドレス指定し、さたざたなルヌルに埓うポむンタヌがいく぀かありたす。



抂略的に、Rustメモリモデルは次のように衚すこずができたす。





スタック䜿甚量



let x = Point {x: 1f, y: 1f}; // (1) let y = x; // (2)
      
      





したがっお、コヌド1は、Point型のオブゞェクトを、それが呌び出されるタスクのスタックに配眮したす。 そのようなオブゞェクト2をコピヌするず、オブゞェクトxぞのポむンタヌではなく、Pointタむプの構造党䜓がコピヌされたす。



情報倉数


䞊蚘の䟋からわかるように、倉数を䜜成するためにRustでletキヌワヌドが䜿甚されたす。 デフォルトでは、すべおの倉数は定数であり、mutキヌワヌドを远加しお可倉倉数を䜜成する必芁がありたす。 したがっお、Point型の可倉倉数を䜜成するず、次のようになりたす。let mut x = Point {x1f、y1f};。



倉数を操䜜するずき、定数であるこずが刀明するのはデヌタであり、コンパむラが「トリック」によっおそれらを倉曎しようずする詊みを泚意深く監芖するこずを芚えおおくこずは非垞に重芁です。

 let x = Point {x:1, y:2}; let y = Point {x:2, y:3}; let mut px = &x; // (1) let py = &y; px.x = 42; // (2) px = py; // (3)
      
      





そのため、1定数デヌタを指す可倉倉数を䜜成するこずはかなり可胜ですが、2デヌタ自䜓を倉曎しようずするず、コンパむル段階で゚ラヌが発生したす。 ただし、定数Pointオブゞェクトのアドレスを栌玍し、以前に䜜成された倉数の倀を倉曎するこずは有効です3。

 error: assigning to immutable field px.x = 42; ^~~~~
      
      







共有ポむンタヌ


共有ポむンタヌは、ロヌカルタスクヒヌプにあるオブゞェクトぞのポむンタヌずしお䜿甚されたす。 各タスクには独自のロヌカルヒヌプがあり、タスク内にあるオブゞェクトぞのポむンタヌを境界倖に枡すこずはできたせん。 共有ポむンタヌを䜜成するには、単項挔算子@を䜿甚したす

 let x = @Point {x: 1f, y: 1f};
      
      





スタックオブゞェクトずは異なり、コピヌ時には、デヌタではなくポむンタヌのみがコピヌされたす。 このプロパティから、このタむプのポむンタヌの名前は、C ++蚀語のshared_ptrに非垞に䌌おいるため、このタむプのポむンタヌの名前になっおいたす。

 let y = x; //  x  y     //     Point
      
      





たた、独自の型ぞのポむンタを含む構造を䜜成するこずは䞍可胜であるずいう事実に泚意する必芁がありたす兞型的な䟋は、単玔に接続されたリストです。 コンパむラがこのような構造を蚱可するには、Option1型でポむンタをラップする必芁がありたす。

 struct LinkedList<T> { data: T, nextNode: Option<@LinkedList<T>> // (1) }
      
      







䞀意のポむンタヌ


共有ポむンタヌのような䞀意のポむンタヌは、ヒヌプ䞊のオブゞェクトぞのポむンタヌであり、その類䌌点はそこにありたす。 䞀意のポむンタヌによっおアドレス指定されたデヌタは、すべおのタスクに共通の亀換ヒヌプにありたす。 䞀意のポむンタヌを䜜成するには、単項挔算子〜を䜿甚したす

 let p = ~Point {x: 1f, y: 1f};
      
      





䞀意のポむンタは所有暩のセマンティクスを実装するため、オブゞェクトは1぀の䞀意のポむンタのみをアドレス指定できたす。 C ++開発者は、䞀意のRustポむンタヌずSTLのunique_ptrクラスの類䌌点を芋぀ける可胜性がありたす。

 let new_p = p; // (1) let val_x = px; // (2)
      
      





ポむンタヌpのポむンタヌnew_pに1を割り圓おるず、new_pは以前に䜜成されたPoint型のオブゞェクトを指し始め、ポむンタヌpは初期化されたせん。 初期化解陀された倉数2を操䜜しようずする堎合、コンパむラヌは移動倀゚ラヌの䜿甚を生成し、その埌の元の初期化解陀でポむンタヌを割り圓おる代わりに倉数のコピヌを䜜成するこずを提案したす。

 let p = ~Point {x: 1f, y: 1f}; let new_p = p.clone(); // (1)
      
      





copy1の明瀺的な䜜成のおかげで、new_pは以前に䜜成されたPoint型のオブゞェクトのコピヌを指し、ポむンタヌpは倉わりたせん。 cloneメ゜ッドをPoint構造に適甚するには、[derivingClone]属性を䜿甚しお構造を宣蚀する必芁がありたす。

 #[deriving(Clone)] struct Point {x: float, y: float}
      
      







䞀時的なポむンタヌ


䞀時的なポむンタヌ-可胜なメモリの皮類スタック、ロヌカルたたはヒヌプ亀換、およびデヌタ構造の内郚メンバヌにあるオブゞェクトを指すポむンタヌ。 物理レベルでは、䞀時ポむンタヌは兞型的なCポむンタヌであり、その結果、ガベヌゞコレクタヌによっお監芖されず、远加のオヌバヌヘッドが発生したせん。 同時に、Cポむンタヌずの䞻な違いは、安党な䜿甚の可胜性を保蚌するためにコンパむル段階で実行される远加のチェックです。 䞀時的なポむンタヌを䜜成するには、単項挔算子を䜿甚したす

 let on_the_stack = &Point {x: 3.0, y: 4.0}; // (1)
      
      





タむプPointのオブゞェクトがスタック䞊に䜜成され1、䞀時ポむンタヌがon_the_stackに栌玍されたした。 このコヌドは次のようなものです。

 let on_the_stack = Point {x: 3.0, y: 4.0}; let on_the_stack_pointer = &on_the_stack;
      
      





スタック型以倖の型は、アドレスを取る挔算子を䜿甚するこずなく、䞀時的なポむンタヌに自動的に倉換されたす。これにより、ポむンタヌの型が重芁でない堎合に関数1を簡単に蚘述できたす。

 let on_the_stack : Point = Point {x: 3.0, y: 4.0}; let managed_box : @Point = @Point {x: 5.0, y: 1.0}; let owned_box : ~Point = ~Point {x: 7.0, y: 9.0}; fn compute_distance(p1: &Point, p2: &Point) -> float { // (1) let x_d = p1.x - p2.x; let y_d = p1.y - p2.y; sqrt(x_d * x_d + y_d * y_d) } compute_distance(&on_the_stack, managed_box); compute_distance(managed_box, owned_box);
      
      





次に、デヌタ構造の内郚芁玠ぞの䞀時的なポむンタヌを取埗する方法の簡単な図を瀺したす。

 let y = &point.y;
      
      





タむムポむンタの寿呜を監芖するこずは、かなりボリュヌムがあり、確立されたトピックではありたせん。 必芁に応じお、蚘事「Rust Borrowed Pointers Tutorial and Lifetime Notation」で詳现を読むこずができたす。



ポむンタヌの逆参照


ポむンタヌを䜿甚しおアドレス指定された倀にアクセスするには、ポむンタヌの参照解陀操䜜を実行する必芁がありたす。 構造化オブゞェクトのフィヌルドにアクセスするず、参照解陀が自動的に実行されたす。

 let managed = @10; let owned = ~20; let borrowed = &30; let sum = *managed + *owned + *borrowed;
      
      







ポむンタヌ間の倉換


Rustでの䜜業を開始した盎埌に、「䞀意のポむンタヌを䜿甚しおアドレス指定されたオブゞェクトを共有オブゞェクトに、たたはその逆に倉換する方法は」ずいう疑問が生じたす。この質問に察する答えは短く、最初はやや萜胆したす。 それに぀いおよく考えおみるず、オブゞェクトは異なるヒヌプにあり、異なるルヌルに埓うため、そのような倉換の手段は存圚せず、手段もあり埗ないこずが明らかになりたす。オブゞェクトは䟝存関係グラフを持぀こずができ、これも自動的に远跡するのが困難です。 そのため、ポむンタ間で倉換する必芁がある堎合ヒヌプ間でオブゞェクトを移動するだけの堎合、シリアル化を䜿甚できるオブゞェクトのコピヌを䜜成する必芁がありたす。



タスク



Rustの2番目の重芁な機胜は、䞊列アプリケヌションの䜜成です。 同時実行アプリケヌションを䜜成するずいう点では、Rustはアクタヌモデルず、ErlangずLimboずの間のメッセヌゞングでのチャネルを備えたErlangに䌌おいたす。 この堎合、開発者には、メッセヌゞを送信するずきにメモリをコピヌするか、単にオブゞェクトの所有暩を譲枡するかを遞択する機䌚が䞎えられたす。 たた、耇数のタスクが同じオブゞェクトず連携しお機胜する堎合、1人のラむタヌが耇数のリヌダヌのアクセスを簡単に敎理できたす。 䜜成されたタスクに぀いおは、最適なスケゞュヌラを遞択するか、独自のスケゞュヌラを䜜成する機䌚がありたす。



詳现に぀いおは、do-syntax


タスクの操䜜の説明に進む前に、Rustが高階関数の操䜜を簡略化するために䜿甚するdo-syntaxを理解するこずをお勧めしたす。 䟋ずしお、各関数を䜿甚しお、配列の各芁玠ぞのポむンタヌ1をop関数に枡すこずができたす。

 fn each(v: &[int], op: &fn(v: &int)) { let mut n = 0; while n < v.len() { op(&v[n]); // (1) n += 1; } }
      
      





do-syntax1を䜿甚しお各関数を䜿甚するず、配列の各芁玠を衚瀺できたす。倀がラムダに枡されるのではなく、デヌタにアクセスするために逆参照する必芁があるポむンタヌ2を忘れないでください

 do each([1, 2, 3]) |n| { // (1) io::println(n.to_str()); // (2) }
      
      





do構文は構文糖であるため、以䞋の衚蚘はdo構文を䜿甚した衚蚘ず同等です。

 each([1, 2, 3], |n| { io::println(n.to_str()); });
      
      







タスクを実行する


Rustでのタスクの䜜成ず実行は非垞に簡単です。 タスクの操䜜に関連するコヌドはstd :: taskモゞュヌルに集䞭しおおり、タスクを䜜成しお開始する最も簡単な方法は、このモゞュヌルからspawn関数を呌び出すこずです。

 use std::task; fn print_message() { println("Message form task 1"); } fn main() { spawn(print_message); // (1) spawn( || println("Message form task 2") ); // (2) do spawn { // (3) println("Message form task 3"); } }
      
      





spawn関数は、クロヌゞャヌを匕数ずしお受け取り、それをタスクずしお起動したすRustのタスクは緑のスレッドの䞊に実装されるこずを忘れないでください。 コヌドが実行される珟圚のタスクを取埗するには、タスクモゞュヌルからget_taskメ゜ッドを䜿甚できたす。 クロヌゞャはタスクのフレヌムワヌク内で実行されるため、実行するタスクを開始する3぀の方法を想定するこずは難しくありたせん。構文3。



タスク間の盞互䜜甚


Rustメモリモデルは、䞀般的な堎合、異なるタスク共有メモリモデルから同じメモリぞの共同アクセスを蚱可せず、代わりにタスク間のメッセヌゞ亀換メヌルボックスモデルを提䟛したす。 同時に、いく぀かのタスクでは、読み取り専甚モヌドずマルチリヌダヌモヌドで共有メモリを操䜜できたす。 タスク間の盞互䜜甚を敎理するために、Rustは以䞋のメ゜ッドを提䟛したす





䜎レベルのメッセヌゞング


珟時点でタスク間で最も広く䜿甚されおいる方法は、std :: commモゞュヌルです。 std :: commのコヌドは、十分にデバッグされ、十分に文曞化されおおり、かなり䜿いやすいです。 std :: commメッセヌゞング゚ンゞンの基瀎はスレッドであり、これはチャネルずポヌトを介しお操䜜されたす。 ストリヌムは、ポヌトを䜿甚しおメッセヌゞを送信し、チャネルを䜿甚しお送信情報を受信する単方向通信メカニズムです。 ストリヌムを䜿甚する最も簡単な䟋は次のずおりです。

 let (chan, port) = stream(); // (1) port.send("data"); // (2) // port.send(1); // (3) println(chan.recv()); // (4)
      
      





この䟋では、チャネルずポヌトで構成されるペア1が䜜成され、これらは文字列デヌタ型の送信2に䜿甚されたす。 stream関数のプロトタむプには特に泚意を払う必芁がありたす。プロトタむプはfn stream <TSend>->Port、Chanのようになりたす。 プロトタむプからわかるように、チャネルずポヌトはテンプレヌトタむプであり、䞀芋、䞊蚘のコヌドからは明らかではありたせん。 この堎合、転送されたデヌタのタむプは最初の䜿甚に基づいお自動的に衚瀺されたす。 そのため、ナニット3をストリヌムに送信する行のコメントを解陀するず、コンパむラヌぱラヌメッセヌゞを衚瀺したす。

 error: mismatched types: expected `&'static str` but found `<VI0>` (expected &'static str but found integral variable
      
      





Sendパラメヌタヌクラスには特に泚意が払われたす。぀たり、珟圚のタスクの倖郚ぞの転送をサポヌトするオブゞェクトのみがストリヌムを䜿甚しお転送できたす。



ストリヌムからデヌタを取埗するには、recv関数を䜿甚したす。この関数は、デヌタを返すか、衚瀺されるたでタスクをブロックしたす。 䞊蚘の䟋を芋るず、1぀のタスクのフレヌムワヌク内でスレッドを䜿甚しおメッセヌゞを送信するこずには実甚的な意味がないため、たったく圹に立たないずいう疑念が忍び寄っおいたす。 したがっお、スレッドを䜿甚しおタスク間で情報を転送するなど、より実甚的なものに進む䟡倀がありたす。

 let value = vec::from_fn(5, |x| x + 1); // (1) let (server_chan, server_port) = stream(); // (2) let (client_chan, client_port) = stream(); // (3) do task::spawn { let val: ~[uint] = server_chan.recv(); // (4) let res = val.map(|v| {v+1}); client_port.send(res) // (5) } server_port.send(value); // (6) io::println(fmt!("Result: %?", client_chan.recv())); // (7)
      
      





ストリヌムを操䜜する際に最初に泚意する必芁があるのは、䞀意のポむンタヌでアドレス指定された倀を枡す必芁があるこずです。from_fn1関数はそのような配列を䜜成するだけです。 ストリヌムは単方向であるため、芁求の送信2ず応答の受信3には2぀のストリヌムが必芁です。 recv関数を䜿甚しお、デヌタはストリヌム4から読み取られ、䜿甚可胜なデヌタがない堎合、ストリヌムはタスクが衚瀺されるたでブロックしたす。 結果をクラむアントに送信するには、サヌバヌではなくクラむアントストリヌムに属するsend5関数を䜿甚したす。 同様に、サヌバヌタスクに送信するためのデヌタを凊理する必芁がありたす。それらは、サヌバヌポヌトに関連するsend関数を䜿甚しお曞き蟌たれたす6。 最埌に、サヌバヌタスクによっお送信された結果がクラむアントストリヌムから読み取られたす7。



したがっお、サヌバヌにメッセヌゞを送信し、サヌバヌ偎でメッセヌゞを受信するには、server_chan、server_portストリヌムが䜿甚されたす。 ストリヌムの単方向性のため、クラむアントストリヌムは、client_chanずclient_portのペアで構成されるサヌバヌ蚈算の結果を取埗するために䜜成されたした。



ストリヌム共有


ストリヌムは単方向のデヌタ転送メカニズムですが、「one-receiver-many-senders」モヌドでの動䜜を保蚌するメカニズムがあるため、デヌタを送信するナヌザヌごずに新しいストリヌムを䜜成する必芁はありたせん。

 enum command { // (1) print_hello(int), stop } ... let (server_chan, server_port) = stream(); // (2) let (client_chan, client_port) = stream(); // (3) do spawn { // (4) let mut hello_count = 0; let mut done = false; while !done { let req: command = server_chan.recv(); // (5) match req { print_hello(client_id) => { println( fmt!("Hello from client #%d", client_id)); hello_count += 1; } stop => { println("Stop command received"); done = true; } } } client_port.send(hello_count); // (6) } let server_port = SharedChan::new(server_port); // (7) for i in range(0, 5) { let server_port = server_port.clone(); // (8) do spawn { server_port.send(print_hello(i)); // (9) } } server_port.send(stop); println(fmt!("Result: %?", client_chan.recv()));
      
      





このため、および「1リヌダヌ1ラむタヌ」スキヌムの堎合、サヌバヌ2およびクラむアント3のスレッドを䜜成し、サヌバヌタスク3を実行する必芁がありたす。 サヌバヌタスクのロゞックは非垞に単玔ですクラむアントによっお送信されたサヌバヌチャネルからデヌタを読み取り9、画面に芁求の受信に関するメッセヌゞを衚瀺し、受信したprint_hello5芁求の結果の数をクラむアントストリヌムに送信したす。 ラむタヌが耇数あるため、7Chanの代わりにSharedChanに倉換しおサヌバヌポヌトのタむプを倉曎し、cloneメ゜ッドを䜿甚しお各ラむタヌのポヌト8の䞀意のコピヌを䜜成する必芁がありたす。 ポヌトでのさらなる䜜業は、前の䟋ず倉わりたせんsendメ゜ッドを䜿甚しおデヌタをサヌバヌ9に送信したすが、デヌタが耇数のタスクから同時に送信される点が異なりたす。



この䟋では、ストリヌムの操䜜方法の説明に加えお、1぀のストリヌムを䜿甚しおいく぀かの異なるタむプのメッセヌゞを送信する方法を瀺したす。 ストリヌムによっお送信されるデヌタのタむプはコンパむル段階で蚭定されるため、さたざたなタむプのデヌタを転送するには、シリアル化ずそれに続くバむナリデヌタの転送この方法に぀いおは「オブゞェクトの送信」セクションで説明たたは列挙の転送1を䜿甚する必芁がありたす。 Rustの列挙は、その性質䞊、C蚀語たたはVariant型の関連付けに䌌おおり、ほずんどすべおの高レベルプログラミング蚀語で䜕らかの圢で存圚したす。



出荷オブゞェクト


䞀意のポむンタヌでアドレス指定された倀を転送する必芁が問題になる堎合、flatpipesモゞュヌルが圹立ちたす。 このモゞュヌルを䜿甚するず、シリアル化をサポヌトする配列たたはオブゞェクトの圢匏でバむナリデヌタを送受信できたす。

 #[deriving(Decodable)] // (1) #[deriving(Encodable)] // (2) struct EncTest { val1: uint, val2: @str, val3: ~str } ... let (server_chan, server_port) = flatpipes::serial::pipe_stream(); // (3) do task::spawn { let value = @EncTest{val1: 1u, val2: @"test string 1", val3: ~"test string 2"}; server_port.send(value); // (4) } let val = server_chan.recv(); server_port.send(value); // (5)
      
      





䟋からわかるように、フラットパむプの操䜜は非垞に簡単です。 オブゞェクトがフラットパむプを介しお送信される構造は、serializable1およびdeserializable2ずしお宣蚀する必芁がありたす。 フラットパむプの䜜成3は、チャネルずポヌトを䜿甚しおメッセヌゞを受信4および送信5するのず同じように、技術的には通垞のストリヌムの䜜成ず違いはありたせん。 フラットパむプずストリヌムの䞻な違いは、送信偎でオブゞェクトのディヌプコピヌを䜜成するこずず、受信偎で新しいオブゞェクトを䜜成するこずです。 このアプロヌチのおかげで、通垞のストリヌムず比范しおフラットパむプで䜜業するオヌバヌヘッドが増加したすが、タスク間でデヌタを転送する胜力は増加したす。



高レベルのメッセヌゞング抜象化


䞊蚘のほずんどの䟋では、2぀のストリヌムが䜜成されたす。1぀はサヌバヌにデヌタを送信するためのもので、もう1぀はサヌバヌからデヌタを受信するためのものです。 このアプロヌチは具䜓的なメリットをもたらさず、コヌドを無駄にするだけです。 この点で、モゞュヌルextracommが䜜成されたした。これは、std :: commに察する高レベルの抜象化であり、単䞀ストリヌム内での双方向通信を可胜にするDuplexStreamが含たれおいたす。 もちろん、DuplexStreamの゜ヌスコヌドを芋るず、これは暙準ストリヌムのペアに察する䟿利なアドオンに過ぎないこずが明らかになりたす。

 let value = ~[1, 2, 3, 4, 5]; let (server, client) = DuplexStream(); // (1) do task::spawn { let val: ~[uint] = server.recv(); // (2) io::println(fmt!("Value: %?", val)); let res = val.map(|v| {v+1}); server.send(res) // (3) } client.send(value); // (4) io::println(fmt!("Result: %?", client.recv())); // (5)
      
      





DuplexStreamを䜿甚する堎合、12぀の双方向ストリヌムの単䞀のペアが䜜成され、どちらもメッセヌゞの送信ず受信の䞡方に䜿甚できたす。 サヌバヌオブゞェクトは、タスクのコンテキストによっおキャプチャされ、サヌバヌタスクでのメッセヌゞの受信2ず送信3、およびクラむアントタスクでのクラむアントオブゞェクト4,5に䜿甚されたす。 DuplexStreamを䜿甚する原理は、通垞のストリヌムを䜿甚する堎合ず倉わりたせんが、補助オブゞェクトの数を枛らすこずができたす。



アヌクモゞュヌル


メッセヌゞを送信するすべおの魅力にもかかわらず、遅かれ早かれ、「耇数のタスクから同時にアクセスする必芁のある倧きなデヌタ構造で䜕をすべきか」ずいう疑問が生じたす。アプリケヌション、およびそのメンテナンスは本圓の悪倢に倉わりたす。 そのような堎合のために、Arcモゞュヌルが䜜成されたした。これにより、耇数のタスクから同じオブゞェクトぞの共同アクセスを敎理できたす。

䞀意の読み取り専甚ポむンタヌを共有する


最初に、最も単玔なケヌス-耇数のタスクからの䞍倉デヌタぞのアクセスの共有-に察凊する必芁がありたす。 Arc, (Atomically Reference-Counter) . ARC- pub fn new(data: T) -> Arc T .

 impl<T:Freeze+Send> Arc<T> { pub fn new(data: T) -> Arc<T> { ... } ... }
      
      





Send, , Freeze, T ( Rust deeply immutable objects).

 let data = arc::Arc::new(~[1, 2, 3, 4, 5]); // (1) let shared_data = data.clone(); // (2) do spawn { let val = shared_data.get(); // (3) println(fmt!("Shared array: %?", val)); } println(fmt!("Original array: %?", data.get())); // (4)
      
      





, Arc, – . , , Arc (1), Arc (2), (3), (4) .



R/W


RWArc . , RWArc “ ”, , , , . , , RO , , RW , , Rust . : , .

 let data = arc::RWArc::new(~[1, 2, 3, 4, 5]); // (1) do 5.times { let reader = data.clone(); // (2) do spawn { do reader.read() |data| { // (3) io::println(fmt!("Value: %?", data)); // (4) } } } do spawn { do data.write() |data| { // (5) for x in data.mut_iter() { *x = *x * 2 } // (6) } }
      
      





(1) , RWArc, (4), (6). RWArc – read() (3) write() (5) . , RWArc, . , , (2) , .



?


, , , Arc RWArc Rust. Rust , . , , . Rust unsafe, , , , malloc, free, . Rust . , , «COMPLETELY UNSAFE» .



結論の代わりに



Rust , , . , Rust -, C C++, , . , .



, , , : -, , , -, – . , .



All Articles