{"action":"created","comment":{"url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/comments/233791320","pull_request_review_id":175286287,"id":233791320,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMzc5MTMyMA==","diff_hunk":"@@ -0,0 +1,494 @@\n+﻿using System;\n+using System.Collections.Generic;\n+using Improbable.WorkerCore;\n+\n+namespace Improbable.Gdk.Core\n+{\n+    internal class DescendingComparer<T> : IComparer<T> where T : IComparable<T>\n+    {\n+        public int Compare(T x, T y)\n+        {\n+            return y.CompareTo(x);\n+        }\n+    }\n+\n+    // We need to avoid changing the underlying map while iterating over it. For example, if a\n+    // callback removes itself, a call to InvokeAll iterates over the map to invoke each callback.\n+    // This then indirectly invokes Remove, which makes the iteration crash.\n+    //\n+    // A simple solution to this problem would be to copy the map for each iteration, but this\n+    // allocates a significant amount of memory each time. Instead, we fix this issue by postponing\n+    // changes to the map until the end of the top-level call to this object. In the mentioned\n+    // example, when InvokeAll indirectly calls Remove, the removal is not done immediately, but\n+    // postponed to the end of the (top-level) InvokeAll call.\n+    //\n+    // The current callbacks are those in the map, plus toAdd, minus toRemove. The changes are\n+    // merged via the UpdateGuard.\n+    internal class Callbacks<T>\n+    {\n+        private SortedDictionary<ulong, Action<T>> map = new SortedDictionary<ulong, Action<T>>();\n+\n+        private SortedDictionary<ulong, Action<T>> mapReversed =\n+            new SortedDictionary<ulong, Action<T>>(new DescendingComparer<ulong>());\n+\n+        private SortedDictionary<ulong, Action<T>> toAdd = new SortedDictionary<ulong, Action<T>>();\n+        private SortedDictionary<ulong, uint> toRemove = new SortedDictionary<ulong, uint>();\n+\n+        // Current call level with 0 for the top-level call.\n+        private int callDepth = 0;\n+\n+        public void Add(ulong key, Action<T> callback)\n+        {\n+            try\n+            {\n+                EnterUpdateGuard();\n+                toAdd.Add(key, callback);\n+                toRemove.Remove(key);\n+            }\n+            finally\n+            {\n+                ExitUpdateGuard();\n+            }\n+        }\n+\n+        public bool Remove(ulong key)\n+        {\n+            try\n+            {\n+                EnterUpdateGuard();\n+\n+                var isInMap = map.ContainsKey(key);\n+                var hadPendingAdd = toAdd.Remove(key);\n+\n+                if (isInMap)\n+                {\n+                    var createdPendingRemove = !toRemove.ContainsKey(key);\n+                    toRemove.Add(key, /* ignored */ 0);\n+                    return createdPendingRemove;\n+                }\n+                else\n+                {\n+                    return hadPendingAdd;\n+                }\n+            }\n+            finally\n+            {\n+                ExitUpdateGuard();\n+            }\n+        }\n+\n+        public void InvokeAll(T op)\n+        {\n+            try\n+            {\n+                EnterUpdateGuard();\n+                foreach (var pair in map)\n+                {\n+                    pair.Value(op);\n+                }\n+            }\n+            finally\n+            {\n+                ExitUpdateGuard();\n+            }\n+        }\n+\n+        public void InvokeAllReverse(T op)\n+        {\n+            try\n+            {\n+                EnterUpdateGuard();\n+                foreach (var pair in map)","path":"workers/unity/Packages/com.improbable.gdk.core/Dispatcher.cs","position":101,"original_position":101,"commit_id":"19e4228747ecb79379308dad13d436d8bbf2c20c","original_commit_id":"5f36f1622cc2e5e63256b0a04faa9cb1cc313aac","user":{"login":"samiwh","id":14006669,"node_id":"MDQ6VXNlcjE0MDA2NjY5","avatar_url":"https://avatars0.githubusercontent.com/u/14006669?v=4","gravatar_id":"","url":"https://api.github.com/users/samiwh","html_url":"https://github.com/samiwh","followers_url":"https://api.github.com/users/samiwh/followers","following_url":"https://api.github.com/users/samiwh/following{/other_user}","gists_url":"https://api.github.com/users/samiwh/gists{/gist_id}","starred_url":"https://api.github.com/users/samiwh/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/samiwh/subscriptions","organizations_url":"https://api.github.com/users/samiwh/orgs","repos_url":"https://api.github.com/users/samiwh/repos","events_url":"https://api.github.com/users/samiwh/events{/privacy}","received_events_url":"https://api.github.com/users/samiwh/received_events","type":"User","site_admin":false},"body":"We can save the performance things for later but this does need to be reversed.","created_at":"2018-11-15T10:39:20Z","updated_at":"2018-11-15T10:39:21Z","html_url":"https://github.com/spatialos/gdk-for-unity/pull/618#discussion_r233791320","pull_request_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/comments/233791320"},"html":{"href":"https://github.com/spatialos/gdk-for-unity/pull/618#discussion_r233791320"},"pull_request":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618"}}},"pull_request":{"url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618","id":230865180,"node_id":"MDExOlB1bGxSZXF1ZXN0MjMwODY1MTgw","html_url":"https://github.com/spatialos/gdk-for-unity/pull/618","diff_url":"https://github.com/spatialos/gdk-for-unity/pull/618.diff","patch_url":"https://github.com/spatialos/gdk-for-unity/pull/618.patch","issue_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/618","number":618,"state":"open","locked":false,"title":"Sidegrade to 13.4 snapshot ","user":{"login":"jamiebrynes7","id":13353733,"node_id":"MDQ6VXNlcjEzMzUzNzMz","avatar_url":"https://avatars1.githubusercontent.com/u/13353733?v=4","gravatar_id":"","url":"https://api.github.com/users/jamiebrynes7","html_url":"https://github.com/jamiebrynes7","followers_url":"https://api.github.com/users/jamiebrynes7/followers","following_url":"https://api.github.com/users/jamiebrynes7/following{/other_user}","gists_url":"https://api.github.com/users/jamiebrynes7/gists{/gist_id}","starred_url":"https://api.github.com/users/jamiebrynes7/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamiebrynes7/subscriptions","organizations_url":"https://api.github.com/users/jamiebrynes7/orgs","repos_url":"https://api.github.com/users/jamiebrynes7/repos","events_url":"https://api.github.com/users/jamiebrynes7/events{/privacy}","received_events_url":"https://api.github.com/users/jamiebrynes7/received_events","type":"User","site_admin":false},"body":"#### Description\r\nThe saga continues (from #611)! This PR comes with:\r\n- A new snapshot!\r\n- Improved commit ordering\r\n- RequestIds as longs instead of uints\r\n- Lots of `CInterop`y-ness\r\n#### Tests\r\nThe standard stuff really.\r\n\r\n#### Documentation\r\nChangelog.\r\n","created_at":"2018-11-14T14:57:25Z","updated_at":"2018-11-15T10:39:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3f38b38d6a5c20d504cb4c43b6fa744a9129733d","assignee":null,"assignees":[],"requested_reviewers":[{"login":"davedissian","id":2639008,"node_id":"MDQ6VXNlcjI2MzkwMDg=","avatar_url":"https://avatars2.githubusercontent.com/u/2639008?v=4","gravatar_id":"","url":"https://api.github.com/users/davedissian","html_url":"https://github.com/davedissian","followers_url":"https://api.github.com/users/davedissian/followers","following_url":"https://api.github.com/users/davedissian/following{/other_user}","gists_url":"https://api.github.com/users/davedissian/gists{/gist_id}","starred_url":"https://api.github.com/users/davedissian/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/davedissian/subscriptions","organizations_url":"https://api.github.com/users/davedissian/orgs","repos_url":"https://api.github.com/users/davedissian/repos","events_url":"https://api.github.com/users/davedissian/events{/privacy}","received_events_url":"https://api.github.com/users/davedissian/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[{"id":1002053376,"node_id":"MDU6TGFiZWwxMDAyMDUzMzc2","url":"https://api.github.com/repos/spatialos/gdk-for-unity/labels/size/XXL","name":"size/XXL","color":"ededed","default":false}],"milestone":null,"commits_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618/commits","review_comments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618/comments","review_comment_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/comments{/number}","comments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/618/comments","statuses_url":"https://api.github.com/repos/spatialos/gdk-for-unity/statuses/19e4228747ecb79379308dad13d436d8bbf2c20c","head":{"label":"spatialos:feature/13.4-snapshot","ref":"feature/13.4-snapshot","sha":"19e4228747ecb79379308dad13d436d8bbf2c20c","user":{"login":"spatialos","id":23554165,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNTU0MTY1","avatar_url":"https://avatars2.githubusercontent.com/u/23554165?v=4","gravatar_id":"","url":"https://api.github.com/users/spatialos","html_url":"https://github.com/spatialos","followers_url":"https://api.github.com/users/spatialos/followers","following_url":"https://api.github.com/users/spatialos/following{/other_user}","gists_url":"https://api.github.com/users/spatialos/gists{/gist_id}","starred_url":"https://api.github.com/users/spatialos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spatialos/subscriptions","organizations_url":"https://api.github.com/users/spatialos/orgs","repos_url":"https://api.github.com/users/spatialos/repos","events_url":"https://api.github.com/users/spatialos/events{/privacy}","received_events_url":"https://api.github.com/users/spatialos/received_events","type":"Organization","site_admin":false},"repo":{"id":137235993,"node_id":"MDEwOlJlcG9zaXRvcnkxMzcyMzU5OTM=","name":"gdk-for-unity","full_name":"spatialos/gdk-for-unity","private":false,"owner":{"login":"spatialos","id":23554165,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNTU0MTY1","avatar_url":"https://avatars2.githubusercontent.com/u/23554165?v=4","gravatar_id":"","url":"https://api.github.com/users/spatialos","html_url":"https://github.com/spatialos","followers_url":"https://api.github.com/users/spatialos/followers","following_url":"https://api.github.com/users/spatialos/following{/other_user}","gists_url":"https://api.github.com/users/spatialos/gists{/gist_id}","starred_url":"https://api.github.com/users/spatialos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spatialos/subscriptions","organizations_url":"https://api.github.com/users/spatialos/orgs","repos_url":"https://api.github.com/users/spatialos/repos","events_url":"https://api.github.com/users/spatialos/events{/privacy}","received_events_url":"https://api.github.com/users/spatialos/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/spatialos/gdk-for-unity","description":"SpatialOS GDK for Unity","fork":false,"url":"https://api.github.com/repos/spatialos/gdk-for-unity","forks_url":"https://api.github.com/repos/spatialos/gdk-for-unity/forks","keys_url":"https://api.github.com/repos/spatialos/gdk-for-unity/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spatialos/gdk-for-unity/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spatialos/gdk-for-unity/teams","hooks_url":"https://api.github.com/repos/spatialos/gdk-for-unity/hooks","issue_events_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/events{/number}","events_url":"https://api.github.com/repos/spatialos/gdk-for-unity/events","assignees_url":"https://api.github.com/repos/spatialos/gdk-for-unity/assignees{/user}","branches_url":"https://api.github.com/repos/spatialos/gdk-for-unity/branches{/branch}","tags_url":"https://api.github.com/repos/spatialos/gdk-for-unity/tags","blobs_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/refs{/sha}","trees_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spatialos/gdk-for-unity/statuses/{sha}","languages_url":"https://api.github.com/repos/spatialos/gdk-for-unity/languages","stargazers_url":"https://api.github.com/repos/spatialos/gdk-for-unity/stargazers","contributors_url":"https://api.github.com/repos/spatialos/gdk-for-unity/contributors","subscribers_url":"https://api.github.com/repos/spatialos/gdk-for-unity/subscribers","subscription_url":"https://api.github.com/repos/spatialos/gdk-for-unity/subscription","commits_url":"https://api.github.com/repos/spatialos/gdk-for-unity/commits{/sha}","git_commits_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/commits{/sha}","comments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/comments{/number}","issue_comment_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/comments{/number}","contents_url":"https://api.github.com/repos/spatialos/gdk-for-unity/contents/{+path}","compare_url":"https://api.github.com/repos/spatialos/gdk-for-unity/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spatialos/gdk-for-unity/merges","archive_url":"https://api.github.com/repos/spatialos/gdk-for-unity/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spatialos/gdk-for-unity/downloads","issues_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues{/number}","pulls_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls{/number}","milestones_url":"https://api.github.com/repos/spatialos/gdk-for-unity/milestones{/number}","notifications_url":"https://api.github.com/repos/spatialos/gdk-for-unity/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spatialos/gdk-for-unity/labels{/name}","releases_url":"https://api.github.com/repos/spatialos/gdk-for-unity/releases{/id}","deployments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/deployments","created_at":"2018-06-13T15:37:54Z","updated_at":"2018-11-14T18:16:23Z","pushed_at":"2018-11-14T18:16:24Z","git_url":"git://github.com/spatialos/gdk-for-unity.git","ssh_url":"git@github.com:spatialos/gdk-for-unity.git","clone_url":"https://github.com/spatialos/gdk-for-unity.git","svn_url":"https://github.com/spatialos/gdk-for-unity","homepage":"https://gdk.improbable.io/spatialos-gdk-unity","size":233548,"stargazers_count":126,"watchers_count":126,"language":"C#","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":20,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":20,"open_issues":9,"watchers":126,"default_branch":"master"}},"base":{"label":"spatialos:master","ref":"master","sha":"aae388d3bf647072cf153241cc0cc5309234e979","user":{"login":"spatialos","id":23554165,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNTU0MTY1","avatar_url":"https://avatars2.githubusercontent.com/u/23554165?v=4","gravatar_id":"","url":"https://api.github.com/users/spatialos","html_url":"https://github.com/spatialos","followers_url":"https://api.github.com/users/spatialos/followers","following_url":"https://api.github.com/users/spatialos/following{/other_user}","gists_url":"https://api.github.com/users/spatialos/gists{/gist_id}","starred_url":"https://api.github.com/users/spatialos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spatialos/subscriptions","organizations_url":"https://api.github.com/users/spatialos/orgs","repos_url":"https://api.github.com/users/spatialos/repos","events_url":"https://api.github.com/users/spatialos/events{/privacy}","received_events_url":"https://api.github.com/users/spatialos/received_events","type":"Organization","site_admin":false},"repo":{"id":137235993,"node_id":"MDEwOlJlcG9zaXRvcnkxMzcyMzU5OTM=","name":"gdk-for-unity","full_name":"spatialos/gdk-for-unity","private":false,"owner":{"login":"spatialos","id":23554165,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIzNTU0MTY1","avatar_url":"https://avatars2.githubusercontent.com/u/23554165?v=4","gravatar_id":"","url":"https://api.github.com/users/spatialos","html_url":"https://github.com/spatialos","followers_url":"https://api.github.com/users/spatialos/followers","following_url":"https://api.github.com/users/spatialos/following{/other_user}","gists_url":"https://api.github.com/users/spatialos/gists{/gist_id}","starred_url":"https://api.github.com/users/spatialos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/spatialos/subscriptions","organizations_url":"https://api.github.com/users/spatialos/orgs","repos_url":"https://api.github.com/users/spatialos/repos","events_url":"https://api.github.com/users/spatialos/events{/privacy}","received_events_url":"https://api.github.com/users/spatialos/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/spatialos/gdk-for-unity","description":"SpatialOS GDK for Unity","fork":false,"url":"https://api.github.com/repos/spatialos/gdk-for-unity","forks_url":"https://api.github.com/repos/spatialos/gdk-for-unity/forks","keys_url":"https://api.github.com/repos/spatialos/gdk-for-unity/keys{/key_id}","collaborators_url":"https://api.github.com/repos/spatialos/gdk-for-unity/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/spatialos/gdk-for-unity/teams","hooks_url":"https://api.github.com/repos/spatialos/gdk-for-unity/hooks","issue_events_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/events{/number}","events_url":"https://api.github.com/repos/spatialos/gdk-for-unity/events","assignees_url":"https://api.github.com/repos/spatialos/gdk-for-unity/assignees{/user}","branches_url":"https://api.github.com/repos/spatialos/gdk-for-unity/branches{/branch}","tags_url":"https://api.github.com/repos/spatialos/gdk-for-unity/tags","blobs_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/refs{/sha}","trees_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/trees{/sha}","statuses_url":"https://api.github.com/repos/spatialos/gdk-for-unity/statuses/{sha}","languages_url":"https://api.github.com/repos/spatialos/gdk-for-unity/languages","stargazers_url":"https://api.github.com/repos/spatialos/gdk-for-unity/stargazers","contributors_url":"https://api.github.com/repos/spatialos/gdk-for-unity/contributors","subscribers_url":"https://api.github.com/repos/spatialos/gdk-for-unity/subscribers","subscription_url":"https://api.github.com/repos/spatialos/gdk-for-unity/subscription","commits_url":"https://api.github.com/repos/spatialos/gdk-for-unity/commits{/sha}","git_commits_url":"https://api.github.com/repos/spatialos/gdk-for-unity/git/commits{/sha}","comments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/comments{/number}","issue_comment_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/comments{/number}","contents_url":"https://api.github.com/repos/spatialos/gdk-for-unity/contents/{+path}","compare_url":"https://api.github.com/repos/spatialos/gdk-for-unity/compare/{base}...{head}","merges_url":"https://api.github.com/repos/spatialos/gdk-for-unity/merges","archive_url":"https://api.github.com/repos/spatialos/gdk-for-unity/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/spatialos/gdk-for-unity/downloads","issues_url":"https://api.github.com/repos/spatialos/gdk-for-unity/issues{/number}","pulls_url":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls{/number}","milestones_url":"https://api.github.com/repos/spatialos/gdk-for-unity/milestones{/number}","notifications_url":"https://api.github.com/repos/spatialos/gdk-for-unity/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/spatialos/gdk-for-unity/labels{/name}","releases_url":"https://api.github.com/repos/spatialos/gdk-for-unity/releases{/id}","deployments_url":"https://api.github.com/repos/spatialos/gdk-for-unity/deployments","created_at":"2018-06-13T15:37:54Z","updated_at":"2018-11-14T18:16:23Z","pushed_at":"2018-11-14T18:16:24Z","git_url":"git://github.com/spatialos/gdk-for-unity.git","ssh_url":"git@github.com:spatialos/gdk-for-unity.git","clone_url":"https://github.com/spatialos/gdk-for-unity.git","svn_url":"https://github.com/spatialos/gdk-for-unity","homepage":"https://gdk.improbable.io/spatialos-gdk-unity","size":233548,"stargazers_count":126,"watchers_count":126,"language":"C#","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":20,"mirror_url":null,"archived":false,"open_issues_count":9,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":20,"open_issues":9,"watchers":126,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618"},"html":{"href":"https://github.com/spatialos/gdk-for-unity/pull/618"},"issue":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/618"},"comments":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/issues/618/comments"},"review_comments":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618/comments"},"review_comment":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/pulls/618/commits"},"statuses":{"href":"https://api.github.com/repos/spatialos/gdk-for-unity/statuses/19e4228747ecb79379308dad13d436d8bbf2c20c"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"samiwh"}}