{"action":"created","issue":{"url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/4228","labels_url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/4228/labels{/name}","comments_url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/4228/comments","events_url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/4228/events","html_url":"https://github.com/openframeworks/openFrameworks/pull/4228","id":100221047,"number":4228,"title":"ofThreadChannel documentation.","user":{"login":"bakercp","id":300484,"avatar_url":"https://avatars.githubusercontent.com/u/300484?v=3","gravatar_id":"","url":"https://api.github.com/users/bakercp","html_url":"https://github.com/bakercp","followers_url":"https://api.github.com/users/bakercp/followers","following_url":"https://api.github.com/users/bakercp/following{/other_user}","gists_url":"https://api.github.com/users/bakercp/gists{/gist_id}","starred_url":"https://api.github.com/users/bakercp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bakercp/subscriptions","organizations_url":"https://api.github.com/users/bakercp/orgs","repos_url":"https://api.github.com/users/bakercp/repos","events_url":"https://api.github.com/users/bakercp/events{/privacy}","received_events_url":"https://api.github.com/users/bakercp/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-08-11T04:03:07Z","updated_at":"2015-08-11T10:20:26Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/openframeworks/openFrameworks/pulls/4228","html_url":"https://github.com/openframeworks/openFrameworks/pull/4228","diff_url":"https://github.com/openframeworks/openFrameworks/pull/4228.diff","patch_url":"https://github.com/openframeworks/openFrameworks/pull/4228.patch"},"body":"Fixes #4225\r\n\r\n@kylemcdonald as one recently using ofThreadChannel, would you mind giving this a proof-read?"},"comment":{"url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/comments/129814623","html_url":"https://github.com/openframeworks/openFrameworks/pull/4228#issuecomment-129814623","issue_url":"https://api.github.com/repos/openframeworks/openFrameworks/issues/4228","id":129814623,"user":{"login":"arturoc","id":48240,"avatar_url":"https://avatars.githubusercontent.com/u/48240?v=3","gravatar_id":"","url":"https://api.github.com/users/arturoc","html_url":"https://github.com/arturoc","followers_url":"https://api.github.com/users/arturoc/followers","following_url":"https://api.github.com/users/arturoc/following{/other_user}","gists_url":"https://api.github.com/users/arturoc/gists{/gist_id}","starred_url":"https://api.github.com/users/arturoc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/arturoc/subscriptions","organizations_url":"https://api.github.com/users/arturoc/orgs","repos_url":"https://api.github.com/users/arturoc/repos","events_url":"https://api.github.com/users/arturoc/events{/privacy}","received_events_url":"https://api.github.com/users/arturoc/received_events","type":"User","site_admin":false},"created_at":"2015-08-11T10:20:26Z","updated_at":"2015-08-11T10:20:26Z","body":"hey @bakercp i was adding notes in several places but there's too many things that i don't think are correct. i think in general it's too long and gives to many implementation details that are not really necessary to know how the class should be used. For example the fact that there's a mutex and specifically an std one doesn't really mean anything for anyone trying to use this class and is not even important since it could perfectly be implemented using a lock free queue (and possibly will be in the future). And the key is really in the condition variable that allows to lock the receiving thread while there's no data to be processed but i wouldn't really mention the particular sync primitive either.\r\n\r\nIn general the most important from this class is that it allows 2 threads (or more but 2 is the most common) to communicate without using explicit locks. That it has a receive method that locks until there's data which allows to completely sleep an auxiliary thread until it has anything to do. The idea behind it is to not use shared memory even behind mutexes and instead send messages from one thread to another which avoids any possible race conditions.\r\n\r\nThere's also details that are not accurate like:\r\n```\r\n+/// While ofThreadChannel will certainly work for \"plain old datatypes\" (e.g.\r\n+/// `int`, `char`, `float`, etc), users are encouraged to use the new\r\n+/// `std::atomic` data types available with C++11 and later. These \"lock-free\"\r\n+/// data types require no special data protection for shared use between threads\r\n+/// and are guaranteed to be \"thread-safe\".\r\n```\r\n\r\nsending primitive types through a channel can be a perfectly normal case. reading and even writing to a primitive number has always been \"thread safe\" in the sense of not crashing the application which is what i think most people would understand by thread safety, what can be avoided by atomics is wrong states of a variable when written by 2 threads but that case is not really what a channel aims to solve.\r\n\r\nI was planning to write something about channels in the blog article but meanwhile if you want to take a look the whole idea is taken from Rust's channels: http://doc.rust-lang.org/std/sync/mpsc/index.html with the main difference that ours doesn't separate receiver and sender and that it could be used as multiple sender multiple receiver but doesn't really make sense and it's better seen as mpsc too. Clojure http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html  and Go http://guzalexander.com/2013/12/06/golang-channels-tutorial.html  have their own versions too although the way those work is slightly different mainly because they can block on the sender while ours won't right now."}}