{"action":"created","comment":{"url":"https://api.github.com/repos/dartsim/dart/pulls/comments/26135502","id":26135502,"diff_hunk":"@@ -63,11 +63,23 @@ class Shape;\n /// may have different policies about how/if their reference frame or name\n /// can be changed. Use the Detachable class to create an Entity whose reference\n /// Frame can be changed arbitrarily.\n-class Entity\n+class Entity : public common::Subscription\n {\n public:\n   friend class Frame;\n \n+  enum Notification {","path":"dart/dynamics/Entity.h","position":19,"original_position":19,"commit_id":"350200ca1466a6fb729073c4fb2150397be7d664","original_commit_id":"350200ca1466a6fb729073c4fb2150397be7d664","user":{"login":"mxgrey","id":1307217,"avatar_url":"https://avatars.githubusercontent.com/u/1307217?v=3","gravatar_id":"","url":"https://api.github.com/users/mxgrey","html_url":"https://github.com/mxgrey","followers_url":"https://api.github.com/users/mxgrey/followers","following_url":"https://api.github.com/users/mxgrey/following{/other_user}","gists_url":"https://api.github.com/users/mxgrey/gists{/gist_id}","starred_url":"https://api.github.com/users/mxgrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mxgrey/subscriptions","organizations_url":"https://api.github.com/users/mxgrey/orgs","repos_url":"https://api.github.com/users/mxgrey/repos","events_url":"https://api.github.com/users/mxgrey/events{/privacy}","received_events_url":"https://api.github.com/users/mxgrey/received_events","type":"User","site_admin":false},"body":"I like the idea of strongly typed enums. How about we do it like this:\r\n\r\n```\r\nenum class Notice : int {\r\n  TRANSFORM,\r\n  VELOCITY,\r\n  // ... etc ...\r\n}\r\n\r\nsendNotification(Entity::Notice::TRANSFORM);\r\n```","created_at":"2015-03-10T16:03:17Z","updated_at":"2015-03-10T16:03:17Z","html_url":"https://github.com/dartsim/dart/pull/343#discussion_r26135502","pull_request_url":"https://api.github.com/repos/dartsim/dart/pulls/343","_links":{"self":{"href":"https://api.github.com/repos/dartsim/dart/pulls/comments/26135502"},"html":{"href":"https://github.com/dartsim/dart/pull/343#discussion_r26135502"},"pull_request":{"href":"https://api.github.com/repos/dartsim/dart/pulls/343"}}},"pull_request":{"url":"https://api.github.com/repos/dartsim/dart/pulls/343","id":30332581,"html_url":"https://github.com/dartsim/dart/pull/343","diff_url":"https://github.com/dartsim/dart/pull/343.diff","patch_url":"https://github.com/dartsim/dart/pull/343.patch","issue_url":"https://api.github.com/repos/dartsim/dart/issues/343","number":343,"state":"open","locked":false,"title":"Subscriptions for destructions and notifications","user":{"login":"mxgrey","id":1307217,"avatar_url":"https://avatars.githubusercontent.com/u/1307217?v=3","gravatar_id":"","url":"https://api.github.com/users/mxgrey","html_url":"https://github.com/mxgrey","followers_url":"https://api.github.com/users/mxgrey/followers","following_url":"https://api.github.com/users/mxgrey/following{/other_user}","gists_url":"https://api.github.com/users/mxgrey/gists{/gist_id}","starred_url":"https://api.github.com/users/mxgrey/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mxgrey/subscriptions","organizations_url":"https://api.github.com/users/mxgrey/orgs","repos_url":"https://api.github.com/users/mxgrey/repos","events_url":"https://api.github.com/users/mxgrey/events{/privacy}","received_events_url":"https://api.github.com/users/mxgrey/received_events","type":"User","site_admin":false},"body":"This pull request introduces a subscription concept, aimed primarily at Entities (but extendable to anything that inherits the Subscription class).\r\n\r\nThe motivation behind this change is that, in a complex framework, it can be difficult (or impossible) to know whether a pointer that you are holding is still valid. If an object is deleted in one part of the code, but another part of the code is holding on to a pointer to that object, there might not be an easy way to communicate that the pointer is now invalid. Additionally, when changes are made to an object in one part of the code, it might be useful to receive a notification about it in another part of the code (similar to the already existing auto-updating features, but more extensible).\r\n\r\nTo get these features, three new classes are introduced in this pull request: Subscription, Subscriber, and sub_ptr.\r\n\r\nSubscription is a base class that is able to send out notifications. Any class that inherits Subscription can be subscribed to. A class that inherits Subscription will *always* send out a destruction notification upon destruction, so all of its Subscribers will be informed when it gets deleted. Inheriting classes also have the ability to send out arbitrary notifications which are simply integers. The inheriting class is expected to enumerate the meanings of its integer notifications.\r\n\r\nSubscriber is a base class that facilitates receiving and managing subscriptions. It offers virtual functions that can be overridden in order to customize the handling of incoming notifications.\r\n\r\nsub_ptr is a templated \"subscribed\" smart pointer that works on any class that inherits Subscription. It allows the user to create a pointer to a Subscription-inheriting class, and that pointer will turn to a nullptr when the class it points to is deleted (no matter where or how it happens). sub_ptr will also keep track of the very last notification sent out by the Subscription.\r\n\r\nThere is no overhead added by the new features in this pull request, except for what the end-users themselves decide to create. If the Subscription model goes unused, it will perform no extra work.\r\n\r\n#### Why not reference-counting / shared pointers?\r\n\r\nThis Subscription model is **not** a memory management tool. It will not help to prevent memory leaks; it only helps to prevent segfaults that could be caused by dereferencing an invalidated pointer. While I do think that DART could benefit greatly from more rigorous memory management, I do not believe that reference-counting or shared pointers are the right solution, because the resources in DART have a very rigid hierarchy of ownership (e.g. Joints are owned by their child BodyNode; BodyNodes are owned by their parent Skeletons; and Skeletons are owned by their World), and reference-counting or shared pointers would undermine that hierarchy. I do have a proposal to help with memory management in DART, but it would be unrelated to this pull request.","created_at":"2015-03-02T23:37:35Z","updated_at":"2015-03-10T16:03:17Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5dc4faa7a78519fbfc39df24042b938657867304","assignee":null,"milestone":{"url":"https://api.github.com/repos/dartsim/dart/milestones/6","html_url":"https://github.com/dartsim/dart/milestones/Release%20DART%205.0","labels_url":"https://api.github.com/repos/dartsim/dart/milestones/6/labels","id":679315,"number":6,"title":"Release DART 5.0","description":"Change plan and log:\r\n  * Math\r\n    * Add BSpline class (#300)\r\n  * Kinematics\r\n    * [Done] Add Frame class and auto-updating for forward kinematics (#319)\r\n    * Add Jacobian related API to Frame\r\n      * For example, getSpatialJacobian(relativeTo, inCoordinatesOf)\r\n  * Collision\r\n    * Decouple dynamics from collision (dependency: kinematics <-- collision <-- dynamics)\r\n    * Improve built-in collision detector -- support primitive shapes, mesh, and deformable mesh\r\n    * Improve fcl collision detector -- merge fcl and fcl_mesh, support primitive shape collision, use broad-phase algorithm\r\n    * Add more primitive shapes (sphere, capsule, and cone)\r\n  * Renderer / GUI\r\n    * [Done] Add the feature to plot 2D trajectories (#324)\r\n    * OpenSceneGraph gui\r\n  * Utils\r\n    * [Done] Fix a bug in loading WorldFile (#325)\r\n    * Improve Skel parser\r\n  * API\r\n    * Remove deprecated APIs in DART 4.x\r\n  * ETC\r\n    * Drop dependency of tinyxml (used in urdf parser)\r\n    * Improve numerical accuracy\r\n    * Use code beautifier\r\n    * Minor improvements: #335\r\n\r\nTarget Gazebo version will be 6.0 (release date: 2015-07-27)\r\n\r\nSupported platforms (compilers)\r\n  * Ubuntu 14.04 LTS, 14.10, and 15.04\r\n    * Require [GCC 4.8](https://gcc.gnu.org/gcc-4.8/) or greater\r\n  * Windows \r\n    * Require [Visual Studio 2013](http://msdn.microsoft.com/en-us/library/dd831853.aspx) or greater\r\n    * (create additional repo that includes all the dependencies together)\r\n  * Mac OS X\r\n    * Require [Clang 3.3](http://llvm.org/releases/3.3/tools/clang/docs/ReleaseNotes.html) or greater","creator":{"login":"jslee02","id":4038467,"avatar_url":"https://avatars.githubusercontent.com/u/4038467?v=3","gravatar_id":"","url":"https://api.github.com/users/jslee02","html_url":"https://github.com/jslee02","followers_url":"https://api.github.com/users/jslee02/followers","following_url":"https://api.github.com/users/jslee02/following{/other_user}","gists_url":"https://api.github.com/users/jslee02/gists{/gist_id}","starred_url":"https://api.github.com/users/jslee02/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jslee02/subscriptions","organizations_url":"https://api.github.com/users/jslee02/orgs","repos_url":"https://api.github.com/users/jslee02/repos","events_url":"https://api.github.com/users/jslee02/events{/privacy}","received_events_url":"https://api.github.com/users/jslee02/received_events","type":"User","site_admin":false},"open_issues":33,"closed_issues":23,"state":"open","created_at":"2014-06-03T15:46:59Z","updated_at":"2015-03-06T19:08:38Z","due_on":"2015-06-01T04:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/dartsim/dart/pulls/343/commits","review_comments_url":"https://api.github.com/repos/dartsim/dart/pulls/343/comments","review_comment_url":"https://api.github.com/repos/dartsim/dart/pulls/comments{/number}","comments_url":"https://api.github.com/repos/dartsim/dart/issues/343/comments","statuses_url":"https://api.github.com/repos/dartsim/dart/statuses/350200ca1466a6fb729073c4fb2150397be7d664","head":{"label":"dartsim:grey/subscriptions","ref":"grey/subscriptions","sha":"350200ca1466a6fb729073c4fb2150397be7d664","user":{"login":"dartsim","id":4191609,"avatar_url":"https://avatars.githubusercontent.com/u/4191609?v=3","gravatar_id":"","url":"https://api.github.com/users/dartsim","html_url":"https://github.com/dartsim","followers_url":"https://api.github.com/users/dartsim/followers","following_url":"https://api.github.com/users/dartsim/following{/other_user}","gists_url":"https://api.github.com/users/dartsim/gists{/gist_id}","starred_url":"https://api.github.com/users/dartsim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dartsim/subscriptions","organizations_url":"https://api.github.com/users/dartsim/orgs","repos_url":"https://api.github.com/users/dartsim/repos","events_url":"https://api.github.com/users/dartsim/events{/privacy}","received_events_url":"https://api.github.com/users/dartsim/received_events","type":"Organization","site_admin":false},"repo":{"id":2418592,"name":"dart","full_name":"dartsim/dart","owner":{"login":"dartsim","id":4191609,"avatar_url":"https://avatars.githubusercontent.com/u/4191609?v=3","gravatar_id":"","url":"https://api.github.com/users/dartsim","html_url":"https://github.com/dartsim","followers_url":"https://api.github.com/users/dartsim/followers","following_url":"https://api.github.com/users/dartsim/following{/other_user}","gists_url":"https://api.github.com/users/dartsim/gists{/gist_id}","starred_url":"https://api.github.com/users/dartsim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dartsim/subscriptions","organizations_url":"https://api.github.com/users/dartsim/orgs","repos_url":"https://api.github.com/users/dartsim/repos","events_url":"https://api.github.com/users/dartsim/events{/privacy}","received_events_url":"https://api.github.com/users/dartsim/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dartsim/dart","description":"Dynamic Animation and Robotics Toolkit","fork":false,"url":"https://api.github.com/repos/dartsim/dart","forks_url":"https://api.github.com/repos/dartsim/dart/forks","keys_url":"https://api.github.com/repos/dartsim/dart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dartsim/dart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dartsim/dart/teams","hooks_url":"https://api.github.com/repos/dartsim/dart/hooks","issue_events_url":"https://api.github.com/repos/dartsim/dart/issues/events{/number}","events_url":"https://api.github.com/repos/dartsim/dart/events","assignees_url":"https://api.github.com/repos/dartsim/dart/assignees{/user}","branches_url":"https://api.github.com/repos/dartsim/dart/branches{/branch}","tags_url":"https://api.github.com/repos/dartsim/dart/tags","blobs_url":"https://api.github.com/repos/dartsim/dart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dartsim/dart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dartsim/dart/git/refs{/sha}","trees_url":"https://api.github.com/repos/dartsim/dart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dartsim/dart/statuses/{sha}","languages_url":"https://api.github.com/repos/dartsim/dart/languages","stargazers_url":"https://api.github.com/repos/dartsim/dart/stargazers","contributors_url":"https://api.github.com/repos/dartsim/dart/contributors","subscribers_url":"https://api.github.com/repos/dartsim/dart/subscribers","subscription_url":"https://api.github.com/repos/dartsim/dart/subscription","commits_url":"https://api.github.com/repos/dartsim/dart/commits{/sha}","git_commits_url":"https://api.github.com/repos/dartsim/dart/git/commits{/sha}","comments_url":"https://api.github.com/repos/dartsim/dart/comments{/number}","issue_comment_url":"https://api.github.com/repos/dartsim/dart/issues/comments{/number}","contents_url":"https://api.github.com/repos/dartsim/dart/contents/{+path}","compare_url":"https://api.github.com/repos/dartsim/dart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dartsim/dart/merges","archive_url":"https://api.github.com/repos/dartsim/dart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dartsim/dart/downloads","issues_url":"https://api.github.com/repos/dartsim/dart/issues{/number}","pulls_url":"https://api.github.com/repos/dartsim/dart/pulls{/number}","milestones_url":"https://api.github.com/repos/dartsim/dart/milestones{/number}","notifications_url":"https://api.github.com/repos/dartsim/dart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dartsim/dart/labels{/name}","releases_url":"https://api.github.com/repos/dartsim/dart/releases{/id}","created_at":"2011-09-19T21:53:51Z","updated_at":"2015-03-06T19:08:15Z","pushed_at":"2015-03-10T10:17:34Z","git_url":"git://github.com/dartsim/dart.git","ssh_url":"git@github.com:dartsim/dart.git","clone_url":"https://github.com/dartsim/dart.git","svn_url":"https://github.com/dartsim/dart","homepage":"http://dartsim.github.io/","size":106460,"stargazers_count":51,"watchers_count":51,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":42,"mirror_url":null,"open_issues_count":82,"forks":42,"open_issues":82,"watchers":51,"default_branch":"master"}},"base":{"label":"dartsim:master","ref":"master","sha":"674ef8f5a461b202a6a721235b1a92305514d178","user":{"login":"dartsim","id":4191609,"avatar_url":"https://avatars.githubusercontent.com/u/4191609?v=3","gravatar_id":"","url":"https://api.github.com/users/dartsim","html_url":"https://github.com/dartsim","followers_url":"https://api.github.com/users/dartsim/followers","following_url":"https://api.github.com/users/dartsim/following{/other_user}","gists_url":"https://api.github.com/users/dartsim/gists{/gist_id}","starred_url":"https://api.github.com/users/dartsim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dartsim/subscriptions","organizations_url":"https://api.github.com/users/dartsim/orgs","repos_url":"https://api.github.com/users/dartsim/repos","events_url":"https://api.github.com/users/dartsim/events{/privacy}","received_events_url":"https://api.github.com/users/dartsim/received_events","type":"Organization","site_admin":false},"repo":{"id":2418592,"name":"dart","full_name":"dartsim/dart","owner":{"login":"dartsim","id":4191609,"avatar_url":"https://avatars.githubusercontent.com/u/4191609?v=3","gravatar_id":"","url":"https://api.github.com/users/dartsim","html_url":"https://github.com/dartsim","followers_url":"https://api.github.com/users/dartsim/followers","following_url":"https://api.github.com/users/dartsim/following{/other_user}","gists_url":"https://api.github.com/users/dartsim/gists{/gist_id}","starred_url":"https://api.github.com/users/dartsim/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dartsim/subscriptions","organizations_url":"https://api.github.com/users/dartsim/orgs","repos_url":"https://api.github.com/users/dartsim/repos","events_url":"https://api.github.com/users/dartsim/events{/privacy}","received_events_url":"https://api.github.com/users/dartsim/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/dartsim/dart","description":"Dynamic Animation and Robotics Toolkit","fork":false,"url":"https://api.github.com/repos/dartsim/dart","forks_url":"https://api.github.com/repos/dartsim/dart/forks","keys_url":"https://api.github.com/repos/dartsim/dart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dartsim/dart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dartsim/dart/teams","hooks_url":"https://api.github.com/repos/dartsim/dart/hooks","issue_events_url":"https://api.github.com/repos/dartsim/dart/issues/events{/number}","events_url":"https://api.github.com/repos/dartsim/dart/events","assignees_url":"https://api.github.com/repos/dartsim/dart/assignees{/user}","branches_url":"https://api.github.com/repos/dartsim/dart/branches{/branch}","tags_url":"https://api.github.com/repos/dartsim/dart/tags","blobs_url":"https://api.github.com/repos/dartsim/dart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dartsim/dart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dartsim/dart/git/refs{/sha}","trees_url":"https://api.github.com/repos/dartsim/dart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dartsim/dart/statuses/{sha}","languages_url":"https://api.github.com/repos/dartsim/dart/languages","stargazers_url":"https://api.github.com/repos/dartsim/dart/stargazers","contributors_url":"https://api.github.com/repos/dartsim/dart/contributors","subscribers_url":"https://api.github.com/repos/dartsim/dart/subscribers","subscription_url":"https://api.github.com/repos/dartsim/dart/subscription","commits_url":"https://api.github.com/repos/dartsim/dart/commits{/sha}","git_commits_url":"https://api.github.com/repos/dartsim/dart/git/commits{/sha}","comments_url":"https://api.github.com/repos/dartsim/dart/comments{/number}","issue_comment_url":"https://api.github.com/repos/dartsim/dart/issues/comments{/number}","contents_url":"https://api.github.com/repos/dartsim/dart/contents/{+path}","compare_url":"https://api.github.com/repos/dartsim/dart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dartsim/dart/merges","archive_url":"https://api.github.com/repos/dartsim/dart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dartsim/dart/downloads","issues_url":"https://api.github.com/repos/dartsim/dart/issues{/number}","pulls_url":"https://api.github.com/repos/dartsim/dart/pulls{/number}","milestones_url":"https://api.github.com/repos/dartsim/dart/milestones{/number}","notifications_url":"https://api.github.com/repos/dartsim/dart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dartsim/dart/labels{/name}","releases_url":"https://api.github.com/repos/dartsim/dart/releases{/id}","created_at":"2011-09-19T21:53:51Z","updated_at":"2015-03-06T19:08:15Z","pushed_at":"2015-03-10T10:17:34Z","git_url":"git://github.com/dartsim/dart.git","ssh_url":"git@github.com:dartsim/dart.git","clone_url":"https://github.com/dartsim/dart.git","svn_url":"https://github.com/dartsim/dart","homepage":"http://dartsim.github.io/","size":106460,"stargazers_count":51,"watchers_count":51,"language":"C++","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":42,"mirror_url":null,"open_issues_count":82,"forks":42,"open_issues":82,"watchers":51,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/dartsim/dart/pulls/343"},"html":{"href":"https://github.com/dartsim/dart/pull/343"},"issue":{"href":"https://api.github.com/repos/dartsim/dart/issues/343"},"comments":{"href":"https://api.github.com/repos/dartsim/dart/issues/343/comments"},"review_comments":{"href":"https://api.github.com/repos/dartsim/dart/pulls/343/comments"},"review_comment":{"href":"https://api.github.com/repos/dartsim/dart/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/dartsim/dart/pulls/343/commits"},"statuses":{"href":"https://api.github.com/repos/dartsim/dart/statuses/350200ca1466a6fb729073c4fb2150397be7d664"}}}}