{"action":"created","comment":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/comments/30153563","id":30153563,"diff_hunk":"@@ -0,0 +1,942 @@\n+% Dining Philosophers\n+\n+For our second project, let’s look at a classic concurrency problem. It’s\n+called ‘the dining philosophers’. It was originally conceived by Dijkstra in\n+1965, but we’ll use the version from [this paper][paper] by Tony Hoare in 1985.\n+\n+[paper]: http://www.usingcsp.com/cspbook.pdf\n+\n+> In ancient times, a wealthy philanthropist endowed a College to accommodate\n+> five eminent philosophers. Each philosopher had a room in which he could\n+> engage in his professional activity of thinking; there was also a common\n+> dining room, furnished with a circular table, surrounded by five chairs, each\n+> labelled by the name of the philosopher who was to sit in it. They sat\n+> anticlockwise around the table. To the left of each philosopher there was\n+> laid a golden fork, and in the centre stood a large bowl of spaghetti, which\n+> was constantly replenished. A philosopher was expected to spend most of his\n+> time thinking; but when he felt hungry, he went to the dining room, sat down\n+> in his own chair, picked up his own fork on his left, and plunged it into the\n+> spaghetti. But such is the tangled nature of spaghetti that a second fork is\n+> required to carry it to the mouth. The philosopher therefore had also to pick\n+> up the fork on his right. When we was finished he would put down both his\n+> forks, get up from his chair, and continue thinking. Of course, a fork can be\n+> used by only one philosopher at a time. If the other philosopher wants it, he\n+> just has to wait until the fork is available again.\n+\n+This classic problem shows off a few different elements of concurrency. The reason\n+is that it's actually slightly tricky to implement: a simple implementation will\n+deadlock. For example, let's consider a simple algorithm that would solve this\n+problem:\n+\n+1. A philosopher picks up the fork on their left.\n+2. They then pick up the fork on their right.\n+3. They eat.\n+4. They return the forks.\n+\n+Now, let’s imagine this sequence of events:\n+\n+1. Philosopher 1 begins the algorithm, picking up the fork on their left.\n+2. Philosopher 2 begins the algorithm, picking up the fork on their left.\n+3. Philosopher 3 begins the algorithm, picking up the fork on their left.\n+4. Philosopher 4 begins the algorithm, picking up the fork on their left.\n+5. Philosopher 5 begins the algorithm, picking up the fork on their left.\n+6. ... ? All the forks are taken, but nobody can eat!\n+\n+There are different ways to solve this problem. We’ll get to our solution in\n+the tutorial itself. For now, let’s get started modelling the problem itself.\n+We’ll start with the philosophers:\n+\n+```rust\n+struct Philosopher {\n+    name: String,\n+}\n+\n+impl Philosopher {\n+    fn new(name: &str) -> Philosopher {\n+        Philosopher {\n+            name: name.to_string(),\n+        }\n+    }\n+}\n+\n+fn main() {\n+    let p1 = Philosopher::new(\"Baruch Spinoza\");\n+    let p2 = Philosopher::new(\"Gilles Deleuze\");\n+    let p3 = Philosopher::new(\"Karl Marx\");\n+    let p4 = Philosopher::new(\"Friedrich Nietzsche\");\n+    let p5 = Philosopher::new(\"Michel Foucault\");\n+}\n+```\n+\n+Here, we make a [`struct`][struct] to represent a philosopher. For now,\n+a name is all we need. We choose the [`String`][string] type for the name,\n+rather than `&str`. Generally speaking, working with a type which owns its\n+data is easier than working with one that uses references. If we wanted to use\n+`&str`s in our `struct`, we’d have to introduce some extra notation:\n+\n+```rust\n+struct Philosopher<'a> {\n+    name: &'a str,\n+}\n+```\n+\n+[struct]: structs.html\n+[string]: strings.html\n+\n+These `'a` markers are called [‘lifetimes’][lifetimes], and help Rust understand\n+the scope in which a lifetime is valid. You’ll notice the annotation in two places:\n+\n+```rust\n+struct Philosopher<'a> {\n+#    name: &'a str,\n+# }\n+```\n+\n+[lifetimes]: lifetimes.html\n+\n+This part says “The `Philosopher` struct has a lifetime parameter named `’a`,”\n+and\n+\n+```rust\n+# struct Philosopher<'a> {\n+name: &'a str,\n+# }\n+```\n+\n+This part says “The `name` field is a string reference with the lifetime `’a`.\n+\n+With a small `struct` like this, it seems kind of obvious: there’s only one\n+reference. But consider these two structs:\n+\n+```rust\n+struct Philosopher1<'a, 'b> {\n+    first_name: &'a str,\n+    last_name: &'b str,\n+}\n+\n+struct Philosopher2<'a> {\n+    first_name: &'a str,\n+    last_name: &'a str,\n+}\n+```\n+\n+The first version says that we have two references that are valid for different\n+scopes, but the second says they’re valid for the same scope.\n+\n+In any case, we’re getting off track. We don’t want references, we want the\n+struct to ‘have ownership’ over the value. The `String` type gives us this:\n+when our `Philosopher` goes out of scope, we’ll free the name as well.\n+\n+Let’s move on:\n+\n+```rust\n+# struct Philosopher {\n+#     name: String,\n+# }\n+impl Philosopher {\n+    fn new(name: &str) -> Philosopher {\n+        Philosopher {\n+            name: name.to_string(),\n+        }\n+    }\n+}\n+```\n+\n+This `impl` block lets us define things on `Philosopher` structs. In this case,\n+we define an ‘associated function’ called `new`. The first line looks like this:\n+\n+```rust\n+# struct Philosopher {\n+#     name: String,\n+# }\n+# impl Philosopher {\n+fn new(name: &str) -> Philosopher {\n+#         Philosopher {\n+#             name: name.to_string(),\n+#         }\n+#     }\n+# }\n+```\n+\n+We take one argument, a `name`, of type `&str`. This is a reference to another\n+string. It returns an instance of our `Philosopher` struct.\n+\n+```rust\n+# struct Philosopher {\n+#     name: String,\n+# }\n+# impl Philosopher {\n+#    fn new(name: &str) -> Philosopher {\n+Philosopher {\n+    name: name.to_string(),\n+}\n+#     }\n+# }\n+```\n+\n+This creates a new `Philosopher`, and sets its `name` to our `name` argument.\n+Not just the argument itself, though, as we call `.to_string()` on it. This\n+will create a copy of the string that our `&str` points to, and give us a new\n+`String`, which is the type of the `name` field of `Philosopher`.\n+\n+Why not accept a `String` directly? It’s nicer to call. If we took a `String`,\n+but our caller had a `&str`, they’d have to call this method themselves. The\n+downside of this flexibility is that we _always_ make a copy. For this small\n+program, that’s not particularly important, as we know we’ll just be using\n+short strings anyway.\n+\n+One last thing you’ll notice: we just define a `Philosopher`, and seemingly\n+don’t do anything with it. Rust is an ‘expression based’ language, which means\n+that almost everything in Rust is an expression which returns a value. This is\n+true of functions as well, the last expression is automatically returned. Since\n+we create a new `Philosopher` as the last expression of this function, we end\n+up returning it.\n+\n+This name, `new()`, isn’t anything special to Rust, but it is a convention for\n+functions that create new instances of structs. Before we talk about why, let’s\n+look at `main()` again:\n+\n+```rust\n+# struct Philosopher {\n+#     name: String,\n+# }\n+# \n+# impl Philosopher {\n+#     fn new(name: &str) -> Philosopher {\n+#         Philosopher {\n+#             name: name.to_string(),\n+#         }\n+#     }\n+# }\n+# \n+fn main() {\n+    let p1 = Philosopher::new(\"Baruch Spinoza\");\n+    let p2 = Philosopher::new(\"Gilles Deleuze\");\n+    let p3 = Philosopher::new(\"Karl Marx\");\n+    let p4 = Philosopher::new(\"Friedrich Nietzsche\");\n+    let p5 = Philosopher::new(\"Michel Foucault\");\n+}\n+```\n+\n+Here, we create five variable bindings with five new philosophers. These are my\n+favorite five, but you can substitute anyone you want. If we _didn’t_ define\n+that `new()` function, it would look like this:\n+\n+```rust\n+# struct Philosopher {\n+#     name: String,\n+# }\n+fn main() {\n+    let p1 = Philosopher { name: \"Baruch Spinoza\".to_string() };\n+    let p2 = Philosopher { name: \"Gilles Deleuze\".to_string() };\n+    let p3 = Philosopher { name: \"Karl Marx\".to_string() };\n+    let p4 = Philosopher { name: \"Friedrich Nietzche\".to_string() };\n+    let p5 = Philosopher { name: \"Michel Foucault\".to_string() };\n+}\n+```\n+\n+That’s much noisier. Using `new` has other advantages too, but even in\n+this simple case, it ends up being nicer to use.\n+\n+Now that we’ve got the basics in place, there’s a number of ways that we can\n+tackle the broader problem here. I like to start from the end first: let’s\n+set up a way for each philosopher to finish eating, and report back that\n+they’re done. As a tiny step, let’s make a method, and then loop through\n+all the philosophers, calling it:\n+\n+```rust\n+struct Philosopher {\n+    name: String,\n+}   \n+\n+impl Philosopher { \n+    fn new(name: &str) -> Philosopher {\n+        Philosopher {\n+            name: name.to_string(),\n+        }\n+    }\n+    \n+    fn done(&self) {\n+        println!(\"{} is done eating.\", self.name);\n+    }\n+}\n+\n+fn main() {\n+    let philosophers = vec![\n+        Philosopher::new(\"Baruch Spinoza\"),\n+        Philosopher::new(\"Gilles Deleuze\"),\n+        Philosopher::new(\"Karl Marx\"),\n+        Philosopher::new(\"Friedrich Nietzsche\"),\n+        Philosopher::new(\"Michel Foucault\"),\n+    ];\n+\n+    for p in &philosophers {\n+        p.done();\n+    }\n+}\n+```\n+\n+Let’s look at `main()` first. Rather than have five individual variable\n+bindings for our philosophers, we make a `Vec<T>` of them instead. `Vec<T>` is\n+also called a ‘vector’, and it’s a growable array type. We then use a\n+[`for`][for] loop to iterate through the vector, getting a reference to each\n+philosopher in turn.\n+\n+[for]: for-loops.html\n+\n+In the body of the loop, we call `p.done()`, which is defined above:\n+\n+```rust,ignore\n+fn done(&self) {\n+    println!(\"{} is done eating.\", self.name);\n+}\n+```\n+\n+In Rust, methods take an explicit `self` parameter. That’s why `done()` is a\n+method, but `new` is an associated function: `new()` has no `self`. For our\n+first version of `done()`, we just print out the name of the philosopher, and\n+mention they’re done eating. Running this program should give you the following\n+output:\n+\n+```text\n+Baruch Spinoza is done eating.\n+Gilles Deleuze is done eating.\n+Karl Marx is done eating.\n+Friedrich Nietzsche is done eating.\n+Michel Foucault is done eating.\n+```\n+\n+Easy enough, they’re all done! We haven’t actually implemented the real problem\n+yet, though, so we’re not done yet!\n+\n+The next version is a bit larger. Here it is:\n+\n+```rust\n+use std::sync::mpsc;\n+use std::sync::mpsc::Sender;\n+\n+struct Philosopher {\n+    name: String,\n+    done: Sender<bool>\n+}   \n+\n+impl Philosopher { \n+    fn new(name: &str, done: Sender<bool>) -> Philosopher {\n+        Philosopher {\n+            name: name.to_string(),\n+            done: done,\n+        }\n+    }\n+    \n+    fn done(&self) {\n+        println!(\"{} is done eating.\", self.name);\n+\n+        self.done.send(true).ok().expect(\"Couldn't finish eating\");\n+    }\n+}\n+\n+fn main() {\n+    let (done_tx, done_rx) = mpsc::channel();\n+\n+    let philosophers = vec![\n+        Philosopher::new(\"Baruch Spinoza\", done_tx.clone()),\n+        Philosopher::new(\"Gilles Deleuze\", done_tx.clone()),\n+        Philosopher::new(\"Karl Marx\", done_tx.clone()),\n+        Philosopher::new(\"Friedrich Nietzsche\", done_tx.clone()),\n+        Philosopher::new(\"Michel Foucault\", done_tx.clone()),\n+    ];\n+\n+    for p in &philosophers {\n+        p.done();\n+    }\n+\n+    for _ in 0..5 {\n+        done_rx.recv().unwrap();\n+    }\n+}\n+```\n+\n+Whew! Lots there. Let’s go through it:\n+\n+```rust,ignore\n+use std::sync::mpsc;\n+use std::sync::mpsc::Sender;\n+```\n+\n+The `use` keyword lets us bring names into scope. In this case, we are going to\n+use two things: the `mspc` module from `std::sync`, and the `Sender` type from\n+said module. As you may have guessed, `mspc` stands for something:\n+multi-producer, single consumer. We’re going to be using Rust’s ‘channel’ types\n+to handle the concurrency here, and they’re in this part of the standard\n+library.\n+\n+```rust,ignore\n+struct Philosopher {\n+    name: String,\n+    done: Sender<bool>\n+}   \n+```\n+\n+When our philosopher is done eating, they’re going to send a boolean value\n+down a channel. The sending end of a channel has the `Sender` type, which\n+we `use`d in the last line.\n+\n+```rust,ignore\n+impl Philosopher { \n+    fn new(name: &str, done: Sender<bool>) -> Philosopher {\n+        Philosopher {\n+            name: name.to_string(),\n+            done: done,\n+        }\n+    }\n+```\n+\n+Now that we have a second field for our struct, we need to define it in\n+`new()`. In this case, we’re going to take it as an argument. We’ll pass this\n+in in `main()`, below.\n+    \n+```rust,ignore\n+    fn done(&self) {\n+        println!(\"{} is done eating.\", self.name);\n+\n+        self.done.send(true).ok().expect(\"Couldn't finish eating\");\n+    }\n+}\n+```\n+\n+We’ve added a new line to `done()`. We use the `send()` method on `Sender`\n+to send `true` down the channel. `send()` returns a `Result`, letting us\n+know if we’ve had some sort of error while trying to send the value. In\n+this case, we want to just crash and throw an error if it doesn’t work,\n+so we use the `ok().expect()` pattern we used in the Guessing Game.\n+\n+```rust,ignore\n+fn main() {\n+    let (done_tx, done_rx) = mpsc::channel();\n+```\n+\n+We need to actually create a channel, and the `mpsc::channel()` function does\n+that. It returns both ends of the channel, the sending and receiving end. We\n+can use a single `let` to bind both ends at the same time, setting both\n+`done_tx` and `done_rx`.","path":"src/doc/trpl/dining-philosophers.md","position":421,"original_position":421,"commit_id":"e6a6ce09aafbafa5a76b50765e778044f887313f","original_commit_id":"e6a6ce09aafbafa5a76b50765e778044f887313f","user":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?v=3","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"body":"This is currently the standard convention for both ends of a channel there \"tx\" is transmission and \"rx\" is receiving, but I also think it's fine to add a few words to explain that here!","created_at":"2015-05-12T16:39:17Z","updated_at":"2015-05-12T16:39:17Z","html_url":"https://github.com/rust-lang/rust/pull/25321#discussion_r30153563","pull_request_url":"https://api.github.com/repos/rust-lang/rust/pulls/25321","_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/comments/30153563"},"html":{"href":"https://github.com/rust-lang/rust/pull/25321#discussion_r30153563"},"pull_request":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/25321"}}},"pull_request":{"url":"https://api.github.com/repos/rust-lang/rust/pulls/25321","id":35190295,"html_url":"https://github.com/rust-lang/rust/pull/25321","diff_url":"https://github.com/rust-lang/rust/pull/25321.diff","patch_url":"https://github.com/rust-lang/rust/pull/25321.patch","issue_url":"https://api.github.com/repos/rust-lang/rust/issues/25321","number":25321,"state":"open","locked":false,"title":"TRPL: dining philosophers","user":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"body":"This is a little rough, and it needs squashed and section headers, but i'd like to get some eyes on it sooner rather than later.","created_at":"2015-05-12T03:25:09Z","updated_at":"2015-05-12T16:39:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"8ab8a01f9e8d815cb9916832fc8acad6207ad514","assignee":{"login":"alexcrichton","id":64996,"avatar_url":"https://avatars.githubusercontent.com/u/64996?v=3","gravatar_id":"","url":"https://api.github.com/users/alexcrichton","html_url":"https://github.com/alexcrichton","followers_url":"https://api.github.com/users/alexcrichton/followers","following_url":"https://api.github.com/users/alexcrichton/following{/other_user}","gists_url":"https://api.github.com/users/alexcrichton/gists{/gist_id}","starred_url":"https://api.github.com/users/alexcrichton/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/alexcrichton/subscriptions","organizations_url":"https://api.github.com/users/alexcrichton/orgs","repos_url":"https://api.github.com/users/alexcrichton/repos","events_url":"https://api.github.com/users/alexcrichton/events{/privacy}","received_events_url":"https://api.github.com/users/alexcrichton/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/rust-lang/rust/pulls/25321/commits","review_comments_url":"https://api.github.com/repos/rust-lang/rust/pulls/25321/comments","review_comment_url":"https://api.github.com/repos/rust-lang/rust/pulls/comments{/number}","comments_url":"https://api.github.com/repos/rust-lang/rust/issues/25321/comments","statuses_url":"https://api.github.com/repos/rust-lang/rust/statuses/e6a6ce09aafbafa5a76b50765e778044f887313f","head":{"label":"steveklabnik:second_tutorial","ref":"second_tutorial","sha":"e6a6ce09aafbafa5a76b50765e778044f887313f","user":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"repo":{"id":7349289,"name":"rust","full_name":"steveklabnik/rust","owner":{"login":"steveklabnik","id":27786,"avatar_url":"https://avatars.githubusercontent.com/u/27786?v=3","gravatar_id":"","url":"https://api.github.com/users/steveklabnik","html_url":"https://github.com/steveklabnik","followers_url":"https://api.github.com/users/steveklabnik/followers","following_url":"https://api.github.com/users/steveklabnik/following{/other_user}","gists_url":"https://api.github.com/users/steveklabnik/gists{/gist_id}","starred_url":"https://api.github.com/users/steveklabnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/steveklabnik/subscriptions","organizations_url":"https://api.github.com/users/steveklabnik/orgs","repos_url":"https://api.github.com/users/steveklabnik/repos","events_url":"https://api.github.com/users/steveklabnik/events{/privacy}","received_events_url":"https://api.github.com/users/steveklabnik/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/steveklabnik/rust","description":"a safe, concurrent, practical language","fork":true,"url":"https://api.github.com/repos/steveklabnik/rust","forks_url":"https://api.github.com/repos/steveklabnik/rust/forks","keys_url":"https://api.github.com/repos/steveklabnik/rust/keys{/key_id}","collaborators_url":"https://api.github.com/repos/steveklabnik/rust/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/steveklabnik/rust/teams","hooks_url":"https://api.github.com/repos/steveklabnik/rust/hooks","issue_events_url":"https://api.github.com/repos/steveklabnik/rust/issues/events{/number}","events_url":"https://api.github.com/repos/steveklabnik/rust/events","assignees_url":"https://api.github.com/repos/steveklabnik/rust/assignees{/user}","branches_url":"https://api.github.com/repos/steveklabnik/rust/branches{/branch}","tags_url":"https://api.github.com/repos/steveklabnik/rust/tags","blobs_url":"https://api.github.com/repos/steveklabnik/rust/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/steveklabnik/rust/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/steveklabnik/rust/git/refs{/sha}","trees_url":"https://api.github.com/repos/steveklabnik/rust/git/trees{/sha}","statuses_url":"https://api.github.com/repos/steveklabnik/rust/statuses/{sha}","languages_url":"https://api.github.com/repos/steveklabnik/rust/languages","stargazers_url":"https://api.github.com/repos/steveklabnik/rust/stargazers","contributors_url":"https://api.github.com/repos/steveklabnik/rust/contributors","subscribers_url":"https://api.github.com/repos/steveklabnik/rust/subscribers","subscription_url":"https://api.github.com/repos/steveklabnik/rust/subscription","commits_url":"https://api.github.com/repos/steveklabnik/rust/commits{/sha}","git_commits_url":"https://api.github.com/repos/steveklabnik/rust/git/commits{/sha}","comments_url":"https://api.github.com/repos/steveklabnik/rust/comments{/number}","issue_comment_url":"https://api.github.com/repos/steveklabnik/rust/issues/comments{/number}","contents_url":"https://api.github.com/repos/steveklabnik/rust/contents/{+path}","compare_url":"https://api.github.com/repos/steveklabnik/rust/compare/{base}...{head}","merges_url":"https://api.github.com/repos/steveklabnik/rust/merges","archive_url":"https://api.github.com/repos/steveklabnik/rust/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/steveklabnik/rust/downloads","issues_url":"https://api.github.com/repos/steveklabnik/rust/issues{/number}","pulls_url":"https://api.github.com/repos/steveklabnik/rust/pulls{/number}","milestones_url":"https://api.github.com/repos/steveklabnik/rust/milestones{/number}","notifications_url":"https://api.github.com/repos/steveklabnik/rust/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/steveklabnik/rust/labels{/name}","releases_url":"https://api.github.com/repos/steveklabnik/rust/releases{/id}","created_at":"2012-12-28T03:07:04Z","updated_at":"2015-04-28T19:37:46Z","pushed_at":"2015-05-12T16:16:34Z","git_url":"git://github.com/steveklabnik/rust.git","ssh_url":"git@github.com:steveklabnik/rust.git","clone_url":"https://github.com/steveklabnik/rust.git","svn_url":"https://github.com/steveklabnik/rust","homepage":"http://www.rust-lang.org","size":296807,"stargazers_count":2,"watchers_count":2,"language":"Rust","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":2,"default_branch":"master"}},"base":{"label":"rust-lang:master","ref":"master","sha":"4b88e8f63eeaf557c916a0a1e73150b028c44c52","user":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"repo":{"id":724712,"name":"rust","full_name":"rust-lang/rust","owner":{"login":"rust-lang","id":5430905,"avatar_url":"https://avatars.githubusercontent.com/u/5430905?v=3","gravatar_id":"","url":"https://api.github.com/users/rust-lang","html_url":"https://github.com/rust-lang","followers_url":"https://api.github.com/users/rust-lang/followers","following_url":"https://api.github.com/users/rust-lang/following{/other_user}","gists_url":"https://api.github.com/users/rust-lang/gists{/gist_id}","starred_url":"https://api.github.com/users/rust-lang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rust-lang/subscriptions","organizations_url":"https://api.github.com/users/rust-lang/orgs","repos_url":"https://api.github.com/users/rust-lang/repos","events_url":"https://api.github.com/users/rust-lang/events{/privacy}","received_events_url":"https://api.github.com/users/rust-lang/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/rust-lang/rust","description":"a safe, concurrent, practical language","fork":false,"url":"https://api.github.com/repos/rust-lang/rust","forks_url":"https://api.github.com/repos/rust-lang/rust/forks","keys_url":"https://api.github.com/repos/rust-lang/rust/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rust-lang/rust/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rust-lang/rust/teams","hooks_url":"https://api.github.com/repos/rust-lang/rust/hooks","issue_events_url":"https://api.github.com/repos/rust-lang/rust/issues/events{/number}","events_url":"https://api.github.com/repos/rust-lang/rust/events","assignees_url":"https://api.github.com/repos/rust-lang/rust/assignees{/user}","branches_url":"https://api.github.com/repos/rust-lang/rust/branches{/branch}","tags_url":"https://api.github.com/repos/rust-lang/rust/tags","blobs_url":"https://api.github.com/repos/rust-lang/rust/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rust-lang/rust/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rust-lang/rust/git/refs{/sha}","trees_url":"https://api.github.com/repos/rust-lang/rust/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rust-lang/rust/statuses/{sha}","languages_url":"https://api.github.com/repos/rust-lang/rust/languages","stargazers_url":"https://api.github.com/repos/rust-lang/rust/stargazers","contributors_url":"https://api.github.com/repos/rust-lang/rust/contributors","subscribers_url":"https://api.github.com/repos/rust-lang/rust/subscribers","subscription_url":"https://api.github.com/repos/rust-lang/rust/subscription","commits_url":"https://api.github.com/repos/rust-lang/rust/commits{/sha}","git_commits_url":"https://api.github.com/repos/rust-lang/rust/git/commits{/sha}","comments_url":"https://api.github.com/repos/rust-lang/rust/comments{/number}","issue_comment_url":"https://api.github.com/repos/rust-lang/rust/issues/comments{/number}","contents_url":"https://api.github.com/repos/rust-lang/rust/contents/{+path}","compare_url":"https://api.github.com/repos/rust-lang/rust/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rust-lang/rust/merges","archive_url":"https://api.github.com/repos/rust-lang/rust/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rust-lang/rust/downloads","issues_url":"https://api.github.com/repos/rust-lang/rust/issues{/number}","pulls_url":"https://api.github.com/repos/rust-lang/rust/pulls{/number}","milestones_url":"https://api.github.com/repos/rust-lang/rust/milestones{/number}","notifications_url":"https://api.github.com/repos/rust-lang/rust/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rust-lang/rust/labels{/name}","releases_url":"https://api.github.com/repos/rust-lang/rust/releases{/id}","created_at":"2010-06-16T20:39:03Z","updated_at":"2015-05-12T15:14:13Z","pushed_at":"2015-05-12T16:31:54Z","git_url":"git://github.com/rust-lang/rust.git","ssh_url":"git@github.com:rust-lang/rust.git","clone_url":"https://github.com/rust-lang/rust.git","svn_url":"https://github.com/rust-lang/rust","homepage":"http://www.rust-lang.org","size":646789,"stargazers_count":10779,"watchers_count":10779,"language":"Rust","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2104,"mirror_url":null,"open_issues_count":2014,"forks":2104,"open_issues":2014,"watchers":10779,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/25321"},"html":{"href":"https://github.com/rust-lang/rust/pull/25321"},"issue":{"href":"https://api.github.com/repos/rust-lang/rust/issues/25321"},"comments":{"href":"https://api.github.com/repos/rust-lang/rust/issues/25321/comments"},"review_comments":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/25321/comments"},"review_comment":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/rust-lang/rust/pulls/25321/commits"},"statuses":{"href":"https://api.github.com/repos/rust-lang/rust/statuses/e6a6ce09aafbafa5a76b50765e778044f887313f"}}}}