{"action":"created","comment":{"url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/comments/120608784","pull_request_review_id":42534978,"id":120608784,"diff_hunk":"@@ -5,222 +5,384 @@\n **Emails: gordon@codeplay.com, ruyman@codeplay.com, michael@codeplay.com**\n **Reply to: michael@codeplay.com, gordon@codeplay.com**\n \n-# Asynchronous managed pointer for Heterogeneous computing\n+# Asynchronous Managed Pointer for Heterogeneous and Distributed Computing (Working Draft)\n \n-## Introduction\n+## Change List\n \n-### Summary\n+### Revision 1:\n \n-This paper proposes an addition to the C\\+\\+ standard library to facilitate the management of a memory allocation which can exist consistently across the memory region of the host CPU and the memory region(s) of one or more remote devices. This addition is in the form of the class template ``managed_ptr``; similar to the ``std::shared_ptr`` but with the addition that it can share its memory allocation across the memory region of the host CPU and the memory region(s) of one or more remote devices.\n+* A new section has been added to describe the requirements of the paper.\n+* Corrections and updates have been made to the example code.\n+* The synopsis has been extended to cover the requirements for the **executor** and **future** types.\n+* Restriction on having only one device within a system capable of performing sycnhornisation operations has been removed.\n+* Implicit synchornisation removed as future work for now as it requires static reflection.\n+* The `managed_ptr` now interfaces with an **executor** rather than an **execution context**.\n+* The `managed_ptr` now has an **executor** associated with it which can be retrieved with the member function `get_local_execution_context()`.\n+* The `managed_ptr` synchronisation member function `get()` and the **executor** class synchronisation member functions `get()`, `then_get()`, `put()` and `then_put()` have been removed, leaving only the global synchronisation functions `get()`, `then_get()`, `put()` and `then_put()`.\n+* The `managed_ptr` no longer has a size associated with it, instead it it represents a pointer to a single value in the same way a `std::shared_ptr` does.\n+* The `managed_ptr` member alias `future_type` has been removed and the global synchronisation functions `get()`, `then_get()`, `put()` and `then_put()` now return `executor_future_t`.\n+* The `managed_ptr` constructors have been altered so there is now only two constructors, one that initialises with an allocator, that is defaulted to the allocator associated with the associated **executor** and one that takes an raw pointer.\n+* The `managed_ptr` now has the member function `is_host_based()` to query if the `managed_ptr` supports host based capabilities.\n+* The `managed_ptr` pointer and dereference operators have been specialised for const instantiations.\n+* The `managed_ptr` now has the member function `is_allocated()` to query if the `managed_ptr` has been allocated on a particular execution context.\n+* The `managed_ptr` member function `is_accessible` now takes an **executor** parameter with a default argument allowing you to query if the `managed_ptr` intance is accessible in another execution context.\n+* The `managed_ptr` member function `is_host_based` is now a static constexpr member variable.\n+* The global synchronisation functions `get()` and `then_get()` no longer take an **executor** parameter, as the associated **executor** can be inferred from the `managed_ptr` parameters.\n+* The global synchronisation operations `sync` and `then_sync` which take an **execution channel** have been added.\n+* Add explicit allocation and deallocation via global allocation functions `allocate`, `then_allocate`, `deallocate` and `then_deallocate`.\n \n-### Aim\n+## TODO\n \n-The aim of this paper is to begin an exploratory work into designing a unified interface for data movement. There are many different data flow models to consider when designing such an interface so it is expected that this paper will serve only as a beginning.\n+* Improve the motivation section.\n+* Clarify the rules for sharing the virtual memory allocation between copies in the same **execution context** and between copies on different **execution contexts**.\n+* Clarify whether each node in a distributed system would have a different **execution context**.\n+* Find a better term for describing the associated **executor**.\n+* Provide examples of both heterogeneous and distributed use cases in the use cases section.\n+* Expand on the section about work flow models.\n \n-The approach proposed in this paper does not include all of the use cases that a complete solution would cover.\n-* This approach makes the assumption that there is only a single host CPU device which is capable of performing synchronisation with **execution contexts**.\n-* This approach does not include an optimized manner of moving data between **execution contexts**.\n-* This approach does not include support for systems which allows for multiple devices to access the same memory concurrently.\n+## Feedback\n \n-## Introduction\n+Much valuable feedback was given dsince the last revision of this paper, this section will identify the issues that were raised and points to their respective solutions.\n \n-### Motivation\n+### Read-only pointers\n \n-In non-heterogeneous or non-distributed systems, there is typically a single device: a host CPU with a single memory region or an area of addressable memory. In contrast, heterogeneous and distributed systems have multiple devices (including the host CPU) with their own discrete memory regions.\n+It was suggested that the `managed_ptr` should be capable of providing read-only access, where write access is restricted, this can be very useful as it allows an implementation to make use of read-only partitions of memory which are often more efficient to access. This is now supported in this paper and is described in section 3.3.\n \n-A device in this respect can be any architecture that exists within a system that is C\\+\\+ programmable; this can include CPUs, GPUs, APUs, FPGAs, DSPs, NUMA nodes, I/O devices and other forms of accelerators.\n+### Allocation of managed memory\n+\n+There were many questions regarding how the how and when memory is allocated for a `managed_ptr` instance and what happens on an allocation failure. Section 3.3.4 has been added which describes these behaviours.\n+\n+### Optimising sycnhornisation between execution contexts\n+\n+It was suggested that it be possible for an implementation to optimise synchronisation of a `managed_ptr` between particular execution contexts rather than having to synchronise via a host execution context. A solution that was being discussed but didn't make it into the first revision of the paper was the concept of channels. This is now supported in this paper and is described in section 3.5.\n+\n+### Discuss memory access in terms of side effects\n+\n+It was suggested that this proposal should describe memory access in terms of visible sided effects rather than caching. This has been introduced as part of the requirement for supporting different memory architectures and the paper has been updated to reflect this.\n+\n+### Host based and remote execution contexts\n+\n+It was asked what would happen if `malloc()` were to be called on a GPGPU, and the answer is this cannot be supported due to hardware limitations on some devices such as GPUs. This question of *execution context* capabilities is described in section 3.3.5.\n+\n+### Supporting systems with unified address spaces\n+\n+It was asked if the `managed_ptr` could allow concurrent access to memory from different execution contexts, this can be very important for systems which have regions of memory shared across discrete devices. This was discussed however did not make it into the first draft of the paper as a solution had not yet been reached. The current proposed solution is described in section 5.1 as future work.\n+\n+## 1. Introduction\n+\n+### 1.1. Summary\n+\n+This paper proposes an extension to the unified interface for execution proposal [1] to facilitate the management and sycnchronisation of a memory allocation across multiple memory region(s). This addition is in the form of the class template `managed_ptr`; similar to the `std::shared_ptr` but with the addition that it can share its memory allocation across the memory region of it's host execution context where it is constructed and the memory region(s) of one or more other host or remote execution contexts.\n+\n+The aim of this paper is to begin an exploratory work into designing a unified interface for data movement. There are many different architectures and data flow models to consider when designing such an interface so it is expected that this paper will serve only as a beginning.\n+\n+### 1.2. Motivation\n+\n+In non-heterogeneous or non-distributed systems, there is typically a single device: a CPU with a single memory region or an area of addressable memory. In contrast, heterogeneous and distributed systems have multiple devices with shared or discrete memory regions.\n+\n+A device in this respect can be any architecture that exists within a system that is C\\+\\+ programmable; this can include CPUs, GPGPUs, APUs, FPGAs, DSPs, NUMA nodes, I/O devices and other forms of accelerators.\n \n This introduces additional complexity for accessing a memory allocation that is not present in current C\\+\\+, the requirement that said memory allocation be available in one of many memory regions within a system throughout a program's execution. For the purposes of this paper, we will refer to such a memory allocation as a managed memory allocation as it describes a memory allocation that is accessible consistently across multiple memory regions. With this requirement comes the possibility that a memory region on a given device may not have the most recently modified copy of a managed memory allocation, therefore requiring synchronisation to move the data.\n \n As the act of dispatching work to a remote device to be executed was once only a problem for third party APIs and so too was the act of moving data to those devices for computations to be performed on. However, now that C\\+\\+ is progressing towards a unified interface for execution [1] the act of moving data to remote devices to be accessible for dispatch via executors is now a problem for C\\+\\+ to solve as well, a unified interface for data movement of such. The act of moving data to a remote device is very tightly coupled with the work being performed on said remote device. This means that this unified interface for data movement must also be tightly coupled with the unified interface for execution.\n \n-### Influence\n+### 1.3. Influence\n \n-This proposal is influenced by the SYCL specification [2] and the work that was done in defining it. This was largely due to the intention of the SYCL specification to define a standard that was based entirely in C\\+\\+ and as in line with the direction of C\\+\\+ as possible. In order to develop this proposal further, we also seek the experience from other programming models including HPX [3], KoKKos [4], Raja [5], and others.\n+This proposal is influenced by many heterogeneous and distributed programming models; including SYCL [2], HPX [3], KoKKos [4], Raja [5], HAM-Offload [?] and MYU [?].\n \n-This approach is also heavily influenced by the proposal for a unified interface for execution [1] as the interface proposed in this paper interacts directly with this.\n+This approach is also heavily influenced by the proposal for a unified interface for execution as the interface proposed in this paper interacts directly with this.\n \n-### Scope of this Paper\n+## 2. Requirements\n \n-There are some additional important considerations when looking at a container for data movement in heterogeneous and distributed systems, however, in order to prevent this paper from becoming too verbose, these have been left out of the scope of the proposed additions here. It is important to note them in relation to this paper for future works, for further details on these additional considerations see the future work section.\n+When attempting to standardise a unified interface for data movement there are many differeent aspects which need to be considered. These come from both the various architectures that this interface aims to abstract and the various data flow models which this interface aims to provide.\n \n-### Naming considerations\n+1. Must support different memory architectures\n+2. Must support different levels of synchronisation\n+3. Must support different data flow models\n+4. Must integrate seemlessly with exexcutors\n+5. Must be interoperable between executor implementations\n+6. Must allow optimisation of data movement between devices\n+7. Must abstract device capabilities\n \n-During the development of this paper, many names were considered both for the `managed_ptr` itself and for its interface.\n+This paper in it's current state aims to satisfy [1], [3], [4], [5], [6], [7], while [2] is still being developed.\n \n-Alternative names that were considered for `managed_ptr` were `temporal` as it described a container which gave temporal access to a managed memory allocation, `managed_container` as the original design was based on the `std::vector` container and `managed_array` as the managed memory allocation is statically sized.\n+### 2.1. Must support different memory architectures\n \n-Alternative names for the `put()` and `get()` interface were `acquire()` and `release()` as you were effectively acquiring and releasing the managed memory allocation and `send()` and `receive()` as you are effectively sending and receiving back the managed memory allocation.\n+In non-heterogeneous or non-distributed systems, there is typically a single device: a host CPU with a single memory region or an area of addressable memory. In contrast, heterogeneous and distributed systems have multiple devices (including the host CPU) often with their own discrete memory regions. A device in this respect can be any architecture that exists within a system that is C\\+\\+ programmable; this can include CPUs, GPGPUs, APUs, FPGAs, DSPs, NUMA nodes, I/O devices and other forms of accelerators.\n+\n+These memory regions can be categorised into two groups. Firstly memory architectures which have a single unfied address space, that is a single area of addressable memory that is accessible across multiple devices, this can optionally be supprted in hardware by devices having the same physical memory or in software by having a cache coherancy layer accessing a shared virtual address space. Secondly memory architectures which have multiple address spaces, therefore having separate discrete areas of addresable memory, often in different physical memory.\n+\n+A unified interface needs to be capable of supporting both of these kinds of memory architectures in such a way that any requirements for cache coherancy is abstracted by the interface and associated coherency model.\n+\n+### 2.2. Must support different levels of synchronisation\n+\n+Different memory architectures, both unified and discrete; may support granularity at different levels. This can either be at the course grained level; where synchronisation between memory regions is performed at the execution function level, or this can be at the fine grained level; where synchronisation between memory regions is performed at the instruction level, allowing access to memory from different devices concurrently, using atomics to specify read and write order.\n+\n+A unified interface needs to be capable of supporting both these levels of synchronisation.\n \n-## Proposed Additions\n+### 2.3. Must support different data flow models\n \n-### Requirements on Execution Context\n+There are also many different data flow models that can be used to describe data and data dependenies in relation to functions of execution. Though it would be impossible to cover all possible models, it's important to make a unified inteface as flexible and utilisable as possible, therfore facilitating a wide range of data flow models.\n \n-For the purposes of this paper, it is necessary to introduce requirements on the **execution context**; the object associated with an **executor** which encapsulates the underlying execution resource on which functions are executed on.\n+One such data flow model that C\\+\\+ is moving towards is that of futures and continuations; the idiom that the invocation of an asycnhornous task returns a future object that represents a dependency on the completion of that task that can be waiting or used to create a continuation task. This allows tasks to be linked together by their dependencies on each other.\n \n-The **execution context** must encapsulate both the execution agents and a global memory region that is accessible from those execution agents. It is required that the memory region of the **execution context** be cache coherent across the execution agents created from the same invocation of an execution function. It is not required that the memory region of the **execution context** be cache coherent across execution agents created from different execution functions or on different **execution contexts**.\n+Another data flow model is one that uses a runtime to create a graph of tasks, which can be optimised.\n \n-*Note: some systems are capable of providing cache coherency across execution functions or **execution contexts** through the availability of shared virtual memory addressing or shared physical memory. This feature is discussed in more detail in the future work section.*\n+Another data flow model is one which simply submits work to be executed and waits for it all to complete, typically called fire and forget execution.\n \n-### Managed Pointer Class Template\n+### 2.4. Must integrate seemlessly with exexcutors\n \n-The proposed addition to the standard library is the ``managed_ptr`` class template (Figure 1). The ``managed_ptr`` is a smart pointer which has ownership of a contiguous managed allocation of memory that is shared between the host CPU and one or more **execution contexts**. It is important to note here that an **execution context** may be on the host CPU accessing the host CPU memory region, however, the interface remains the same.\n+As data movement is tightly coupled with executtion, it is nessesary for a unified interface for data movement to be integrated with the unified interface for execution. This means such a unified interface must integrate seemlessly with the current design philosophy of executors, in that it must be compatible for the range of control structures which the executors abstraction supports and must support te range of platforms which executors can target.\n \n-At any one time the managed memory allocation can exist in the memory regions of the host CPU and any number of **execution contexts**. However, the managed memory allocation may only be accessible in one of these memory regions at any given time. This memory region is said to be the accessible memory region. If the accessible memory region is of the host CPU, the host CPU is said to be accessible and if the accessible memory region is of an **execution context** that **execution context** is said to be the accessible **execution context**.\n+At the same time a unified interface for data movement must exist at a high level of abstraction and must avoid introducing too many requirements on executor implementations, in order to avoid introducing complex requirements for heterogeneous or distributed memory architectures into C\\+\\+.\n \n-For the host CPU to be accessible or for an **execution context** to be the accessible **execution context**, if it is not already, a synchronisation operation is required. A synchronisation operation is an implementation defined asynchronous operation which moves the data from the currently accessible memory region to another memory region. From the point at which a synchronisation operation is triggered the currently accessible memory region is no longer accessible. Once the synchronisation point is complete the memory region the data is being moved to is now the accessible memory region.\n+### 2.5. Must be interoperable between executor implementations\n \n-Synchronisation operations are course grained synchronisation in that they synchronise the entire managed memory allocation of a ``managed_ptr``.\n+The unified interface for execution will have may different implementation which target different platforms and therefore a unified interfacec for data movement would too require this range of implementations.\n \n-*Note: some systems are capable of providing finer-grained synchronisation via atomic operations, however, this is generally only when there is shared virtual memory addressing or shared physical memory. This feature is discussed in more detail in the future work section.*\n+It's important therefore that a unified interface for data movement be interoperable between different executor implementations, it must be possible to synchronise data between the memory region of one executor implementation and another.\n \n-There are three ways in which a synchronisation operation can be triggered, each of which will be described in more detail further on. The first is by calling a member function or customisation point of an **executor** triggering a synchronisation operation to the memory region of said **execution context**. The second is by calling the ``get()`` member function on the ``managed_ptr`` itself as this will call the above-mentioned member functions of the **executor**. The third is by passing a ``managed_ptr`` to an **executor** control structure such as ``async()``, as this will implicitly trigger the above-mentioned member functions on the **executor**.\n+### 2.6. Must allow optimisation of data movement between devices\n \n-Any ``managed_ptr`` can only have a single host CPU that can be accessible for any given application, that is capable of triggering synchronisation operations.\n+A unified interface for data movement must provide interoperability bewteen implementations, however this will likely be inneficient as it will likely require a middle man stage that facilitates the required operations of each implementation.\n \n-*Note: some systems may wish to have multiple host CPU nodes which are capable of triggering synchronisation operations. This feature is discussed in more detail in the future work section.*\n+Therefore it's important that a unified interface for data movement provide a facility for customising data movement between particular memory regions in order to optimise those operations rather than relying on a generic middle man.\n \n-If the host CPU is not accessible the ``managed_ptr`` is required to maintain a pointer to the accessible **execution context** in order for it to perform synchronisation operations.\n+### 2.7. Must abstract device capabilities\n \n-Memory is only required to be allocated where it is accessible. The managed memory allocation is only required to be allocated on the host CPU memory region if the ``managed_ptr`` is constructed with a pointer or if a synchronisation operation is triggered to the host CPU. Managed memory allocation is only required to be allocated on the memory region of an **execution context** if a synchronisation operation is triggered to that **execution context**.\n+Many heterogeneous architectures such as GPGPUs, DSPs or FPGAs have considerable restrictions on the code that is executed on the compared to that of a CPU, such no capability to dynamically allocate memory or signal directly with other devices during execution and the level of forward proress guarantees the device can provide. This means that a unified inteface for data movement needs to take into consideration these restrictions in the design of how memory on devices is allocated and synchronised.\n+\n+A typical example of this is that a CPU cluster would have no problem allocating a `managed_ptr` on any ne of it's nodes and peforming synchronisation operations on any node, where as with a typical GPU all allocation and sycnhronisation must be done from a host CPU device priory to execution.\n+\n+## 3. Proposed Additions\n+\n+### 3.1. Header `<execution>` synopis\n \n ```cpp\n namespace std {\n namespace experimental {\n+inline namespace concurrency_v2 {\n namespace execution {\n \n+/* extensions to executor classes */\n+class executor {\n+  ...\n+\n+  /* aliases */\n+  using global_memory_allocator_type = __global_memory_allocator_type__;\n+\n+  /* member functions */\n+  global_memory_allocator_type global_memory_allocator() const;\n+\n+  ...\n+};\n+\n /* managed_ptr class template */\n-template <class T>\n+template <typename T>\n class managed_ptr {\n public:\n \n   /* aliases */\n-  using value_type      = T;\n-  using pointer         = value_type *;\n-  using const_pointer   = const value_type *;\n-  using reference       = value_type &;\n-  using const_reference = const value_type &;\n-  using future_type     = __future_type__;\n+  using value_type             = __undefined_attributes__ T;\n+  using pointer                = value_type *;\n+  using const_pointer          = const value_type *;\n+  using reference              = value_type &;\n+  using const_reference        = const value_type &;\n+  using executor_type          = __executor_type__;\n+  using default_allocator_type = executor_type::global_memory_allocator_type;\n+\n+  /* constexpr values */\n+  static constexpr bool is_host_based = __is_host_based__;\n \n   /* constructors */\n-  managed_ptr(size_t); // (1)\n-  managed_ptr(pointer, size_t); // (2)\n-  managed_ptr(const_pointer, size_t); // (3)\n-  template <typename allocatorT>\n-  managed_ptr(size_t, allocatorT); // (4)\n+  managed_ptr(pointer); // (1)\n+  template <typename Allocator>\n+  managed_ptr(Allocator allocator = default_allocator_type{}); // (2)\n \n-  /* copy/move constructors/operators, destructor */\n+  /* special member functions */\n   managed_ptr(const managed_ptr &);\n-  managed_ptr(const managed_ptr &&);\n+  managed_ptr(managed_ptr &&);\n   managed_ptr &operator=(const managed_ptr &);\n-  managed_ptr &operator=(const managed_ptr &&);\n+  managed_ptr &operator=(managed_ptr &&);\n   ~managed_ptr();\n \n-  /* synchronisation member functions */\n-  bool is_accessible() const;\n-  future_type get() const;\n+  /* member functions */\n+  executor_type &executor() const;\n+  template <typename Executor>\n+  bool is_allocated(Executor = executor_type{}) const;\n+  template <typename Executor>\n+  bool is_accessible(Executor = executor_type{}) const;\n+\n+  /* operators of const T instantiation */\n+  const_reference operator*() const;\n+  const_pointer operator->() const;\n+\n+  /* operators of non-const T instantiation */\n+  reference operator*() const;\n+  pointer operator->() const;\n+};\n+\n+/* extended retuirements for executor_future_t */\n+template <typename T>\n+class executor_future_t {\n+  ...\n \n-  /* operators */\n-  reference operator[](int index);\n-  const_reference operator[](int index) const;\n+  /* synchronisation member functions */\n+  template <typename Executor, typename... ManagedPtrN>\n+  future_type_t<Executor, void> put(Executor, ManagedPtrN...);\n+  template <typename... ManagedPtrN>\n+  future_type_t<Executor, void> get(ManagedPtrTN...);\n+  template <typename SynchronisationChannel, typename SrcExecutor,\n+            typename DestExecutor, typename... ManagedPtrN>\n+  future_type_t<Executor, void>\n+  sync(SynchronisationChannel = __default_synchronisation_channel__{},\n+       SrcExecutor, DestExecutor, ManagedPtrN...);\n+\n+  /* allocation member functions */\n+  template <typename Executor, typename... ManagedPtrN>\n+  future_type_t<Executor, void> allocate(Executor, ManagedPtrN...);\n+  template <typename Executor, typename... ManagedPtrN>\n+  future_type_t<Executor, void> deallocate(Executor, ManagedPtrN...);\n \n-  /* other member functions */\n-  size_t size() const;\n+  ...\n };\n+\n+/* synchronisation functions */\n+template <typename Executor, typename... ManagedPtrN>\n+future_type_t<Executor, void> put(Executor, ManagedPtrN...);\n+template <typename Executor, typename Predicate, typename... ManagedPtrN>\n+future_type_t<Executor, void> then_put(Executor, Predicate, ManagedPtrN...);\n+template <typename... ManagedPtrN>\n+future_type_t<Executor, void> get(ManagedPtrTN...);\n+template <typename Predicate, typename... ManagedPtrN>\n+future_type_t<Executor, void> then_get(Predicate, ManagedPtrN...);\n+template <typename SynchronisationChannel, typename SrcExecutor,\n+          typename DestExecutor, typename... ManagedPtrN>\n+future_type_t<Executor, void>\n+sync(SynchronisationChannel = __default_synchronisation_channel__{},\n+     SrcExecutor, DestExecutor, ManagedPtrN...);\n+template <typename SynchronisationChannel, typename SrcExecutor,\n+          typename DestExecutor, typename Predicate, typename... ManagedPtrN>\n+future_type_t<Executor, void>\n+then_sync(SynchronisationChannel = __default_synchronisation_channel__{},\n+          SrcExecutor, DestExecutor, Predicate, ManagedPtrN...);\n+\n+/* allocation functions */\n+template <typename Executor, typename... ManagedPtrN>\n+future_type_t<Executor, void> allocate(Executor, ManagedPtrN...);\n+template <typename Executor, typename Predicate, typename... ManagedPtrN>\n+future_type_t<Executor, void> then_allocate(Executor, Predicate, ManagedPtrN...);\n+template <typename Executor, typename... ManagedPtrN>\n+future_type_t<Executor, void> deallocate(Executor, ManagedPtrN...);\n+template <typename Executor, typename Predicate, typename... ManagedPtrN>\n+future_type_t<Executor, void> then_deallocate(Executor, Predicate,\n+                                              ManagedPtrN...);\n+\n }  // namespace execution\n+}  // namespace concurrency_v2\n }  // namespace experimental\n }  // namespace std\n ```\n+*Figure 1: Execution synopsis*\n \n-*Figure 1: managed_ptr class template*\n+### 3.2. Requirements on Executor and Execution Contex\n \n-The ``managed_ptr`` class template has a single template parameter; ``T`` specifying the type of the elements.\n+In order to facilitate the `managed_ptr`, it is necessary to introduce requirements on the *executor* and the *execution context*; the class associated with an *executor* which encapsulates the underlying execution resource on which *execution agents* are executed.\n \n-The type parameter ``T`` specifies the element type of the container, any ``T`` satisfies the ``managed_ptr`` element type requirements if:\n+#### 3.2.1. Execution Context Memory Region\n \n-* ``T`` is a standard layout type.\n-* ``T`` is copy constructible.\n+In addition to a number of *execution agents* an *execution context* must also encapsulate at least one memory region that is concurrently accessible by all *execution agents* of any single invcation of an execution function. It is not required that the memory region be concurrently accessible to *execution agents* of another invocation of an execution function or *execution agents* executing on a different *execution context*.\n \n-A  ``managed_ptr`` can be constructed in a number of ways:\n+> This requirement currently satisfies the course grained level of synchronisation described in requirement 2. These requirements will be loosened in a later iteration of this paper when a suitable interface for fine grained sycnrhonisation is included. The curent proposal for this is described in section 5.1 as future work.\n \n-* for constructor (1) the  ``managed_ptr`` allocates the number of elements specified by the `size_t` parameter using the default allocator, therefore allocating on the host remote device memory region.\n-* for constructor (2) the  ``managed_ptr`` takes ownership of the pointer parameter.\n-* for constructor (3) the  ``managed_ptr`` takes ownership of the const_pointer parameter.\n-* for constructor (4) the  ``managed_ptr`` allocates the number of elements specified by the `size_t` parameter using the allocator specified by the allocatorT parameter.\n+#### 3.2.2. Executor Global Memory Allocator\n \n-The default constructor T is not called for the elements of the ``managed_ptr`` during allocation.\n+The *execution context* must also provide an alias to an allocator type called `global_memory_allocator_type` that is capable of allocating memory in it's memory region, and a member function for retrieving an instance of this type called `global_memory_allocator()`.\n \n-The destructor is not required to perform any synchronisation operations.\n+### 3.3. Managed Pointer Class Template\n \n-The member function ``get()`` triggers a synchronisation operation to the host CPU if the host CPU returns a ``future_type`` object which can be used to wait on the operation completing. If an error occurred during the synchronisation point or the pointer to the accessible **execution context** is no longer valid then an exception is thrown and stored within the ``future_type`` that is returned. It is undefined to call ``get()`` within a function executing on an **execution context**.\n+The proposed addition to the standard library is the `managed_ptr` class template. The `managed_ptr` is a smart pointer which has ownership of a contiguous managed allocation of memory that can be shared between any number of devices  represented by their respective *execution contexts*.\n \n-The member function ``is_accessible()`` returns a boolean specifying whether the host CPU is accessible.\n+The `managed_ptr` class template has a single template parameter; `T` specifying the type of the pointer.\n \n-The subscript operator returns a reference to an element of the pointer at the index specified by ``index`` parameter. If the subscript operator is called on the host CPU and the host CPU is not accessible then the return value is undefined. If the subscript operator is called within a function executing on an **execution context** and said **execution context** is not the accessible **execution context** then the return value is undefined.\n+The type parameter `T` specifies the pointer type, any `T` satisfies the `managed_ptr` pointer type requirements if:\n \n-The member function ``size`` returns the number of elements of type ``T`` stored within the managed allocation.\n+> Another solution for read-only access was considered where access to a `managed_ptr` instance could be dynamically specified via properties using the proposed `array_ref` interface [10]. However it was felt that this approach would be too verbose and would introduce unnessesary overhead for casess which did not require the properties to be specified. Additionally as many implementation would wish to make use of read-only partitions of memory this could require an implementation to copy in an out of this memory partition dynamically which could introduce opaque latency in synchronisation.\n \n-### Extensions to Executors and Execution Contexts\n+* `T` is a standard layout type.\n+* `T` is trivially copy constructible.\n \n-In order to facilitate the synchronisation operations required to support the **managed_ptr** the following extensions are proposed for the unified interface for execution.\n+If `T` is a const type then the `managed_ptr` is considered to be read-only. This allows implementations to optimize the allocation of memory in read-only segments of the memory region. Additionally the de-reference and pointer operators return a const pointer and reference respectively preventing writing to the memory.\n \n-These extensions are in the form of member functions and global customisation point functions which each trigger a synchronisation operation. The ``put()`` and ``then_put()`` functions trigger a synchronisation operation to an **execution context**. The ``get()`` and ``then_get()`` functions trigger a synchronisation operation to the host CPU. Each function takes a variadic set of ``managed_ptr`` and triggers a synchronisation operation for each of them and the global customisation point functions take an **executor** parameter. Each function returns a ``future_type`` object that can be used to wait on the synchronisation operation. The ``then_get()`` and ``then_put()`` functions also take an ``future_type`` predicate parameter.\n+#### 3.3.1. Construction and destuction\n \n-```cpp\n-namespace std {\n-namespace experimental {\n-namespace execution {\n+A `managed_ptr` can be constructed in two ways:\n \n-/* executor classes */\n-class <executor-class> {\n-  ...\n+* for constructor (1) the  `managed_ptr` takes an existing pointer and does not allocate memory.\n+* for constructor (2) the  `managed_ptr` allocates using the allocator specified by the allocatorT parameter, which defaults to the allocator of the associated *executor* if one is not provided.\n \n-  template <typename... ManagedPtrTN>\n-  executor_future_t<<executor-class>, void> put(ManagedPtrTN...);\n-  template <typename... ManagedPtrTN>\n-  executor_future_t<<executor-class>, void> get(ManagedPtrTN...);\n-  template <typename Predicate, typename... ManagedPtrTN>\n-  executor_future_t<<executor-class>, void> then_put(Predicate pred, ManagedPtrTN...);\n-  template <typename Predicate, typename... ManagedPtrTN>\n-  executor_future_t<<executor-class>, void> then_get(Predicate pred, ManagedPtrTN...);\n+The default constructor for `T` must not be called by the `managed_ptr` during allocation.\n \n-  ...\n-};\n+The destructor must not perform any synchronisation operations.\n \n-/* customisation points */\n-template <typename Executor, typename... ManagedPtrTN>\n-executor_future_t<Executor, void> put(Executor, ManagedPtrTN...);\n-template <typename Executor, typename... ManagedPtrTN>\n-executor_future_t<Executor, void> get(Executor, ManagedPtrTN...);\n-template <typename Predicate, typename Executor, typename... ManagedPtrTN>\n-executor_future_t<Executor, void> then_put(Predicate pred, Executor, ManagedPtrTN...);\n-template <typename Predicate, typename Executor, typename... ManagedPtrTN>\n-executor_future_t<Executor, void> then_get(Predicate pred, Executor, ManagedPtrTN...);\n+#### 3.3.2. Execution context capabilities\n \n-}  // namespace execution\n-}  // namespace experimental\n-}  // namespace std\n-```\n+In order to support a wide range of systems, both heterogneous and distributed, a high level absraction for the `managed_ptr` is nessesary, however not all devices will be able to support of all of a `managed_ptr`s capabilities.\n+\n+As the `managed_ptr` can be passed between and used on different devices it can therefore have different capabilities depending on where it is currently being used. The `managed_ptr` will likely be compiled separately or a least have different restrictions imposed on the code that is executed depending on where it s used. It is therefore important to be able to determine what capabilities the `managed_ptr` supports where it is being used.\n+\n+The major distinction is whether or not the `executor_type` of a `managed_ptr` is a *host* which or a *remote*. If the `executor_type` is a *host* then it supports host based capabilities; being able to perform allocation and sycnhronisation operations, if it is a *remote* it does not. Whether the `executor_type` of a `managed_ptr` is a *host* can be queried with the static constexpr bool `is_host_based`.\n+\n+> For the purposes of this paper the capabilities of host and remote execution contexts simply state that allocation and sycnhronisation operations can only be performed by host execution contexts. In reality the capabilities of execution contexts will be far more complex and will require an depth interface for querying said capabilities. However this problem of language capabilities on execution contexts particularly for heterogeneous architectures is a much larger problem for C\\+\\+ that goes beyond the scope of this paper and indeed the executors proposal as well.\n \n-*Figure 2: Extensions to unified interface for execution*\n+#### 3.3.3. Memory accessibiity\n \n-As described previously there are three ways in which a synchronisation operation can be triggered, and these are separated into explicit and implicit.\n+During the lieftime of a `managed_ptr` it's managed memory allocation can exist in the memory region(s) associated with any number of *execution contexts*, but may only be accessible in one of these memory regions at any given time. The *execution context* who's memory region is currently accessible is said to be the accessible *execution context*.\n \n-The first is by calling one of the member functions or global customisation point functions described above. This will trigger a synchronisation operation to the memory region of the **execution context** associated with the **executor**. This method is useful as it allows finer control over the synchronisation operations by chaining continuations. This is implicit.\n+> This limited may be relaxed in a future version of the paper when a `managed_ptr` can be concurrently accessed in more than one memory region. In this case there could be more than one accessible memory region. This is further described in section 5.1.\n \n-The second is by calling the ``get()`` member function on the ``managed_ptr`` itself as this will implicitly trigger a call to ``get()`` on the current accessible **execution context** if the host CPU is not currently accessible. This method is useful when you want to synchronise data back to the host CPU in order to use the resulting data in regular sequential code. This is explicit.\n+The `managed_ptr` must maintain a reference to the current accessible *execution context*.\n \n-The third is by passing a ``managed_ptr`` to an executor control structure such as ``async()``, as this will implicitly trigger a call to the ``put()`` member function on the **executor**. If the host CPU is not accessible at this point then this will implicitly trigger a call to``get()`` on the ``managed_ptr`` which will subsequently implicitly trigger a call to ``get()`` on the currently accessible **execution context**. This method is useful as it allows you to simply pass a  ``managed_ptr`` directly to a control structure without requiring an explicit call to ``put()``. This is implicit.\n+The associated *execution context* and *executor* of a `managed_ptr` can also be accessible, the `managed_ptr` has a member function for querying wether the associated *execution context* and *executor* is accessible; `is_accessible()`.\n \n-## Examples\n+The data at the memory region of the `managed_ptr`s associated *execution context* and *executor* can be read and modified (if the type `T` is a non-const type) via the de-reference and pointer operators.\n \n-There is a wide range of user cases that affect the design of a potential interface when it comes to asynchronous tasks and the movement of the data that those tasks require, however for the purposes of this paper the following example should provide a base requirement for the features this paper proposes.\n+#### 3.3.4. Resource aquisition\n \n-The following examples show how the features that will be presented in this paper can be used to move data from the host CPU memory region to the memory region of a GPU in order to perform an operation on said data via the **executor** interface.\n+The `managed_ptr` must allocate memory within the memory region of any execution context which that `managed_ptr` is accessible on via that execution context's allocator. This does not have to be in tamdem or on construction of the `managed_ptr` instance, the point at which allocation happens for each execution context is implementation defined, the only requirement is that the memory must be allocated (if not already so) prior to the `managed_ptr` being accessed on said execution context. Additionally the `managed_ptr` must deallocate in all memory regions that the `managed_ptr` instance has been allocated on, during its destructor.\n \n-The first example shows how this would look using the explicit interface for synchronisation operations (figure 3) and the second shows how this would look using the implicit interface for synchronisation operations (Figure 4).\n+If a user wishes to explicitly allocate or deallocate memory for a `managed_ptr` instance on a particular execution context, this can be done by calling the allocation operations `allocate`, `then_allocate`, `deallocate` and `then_deallocate`. Each of which is an asycnhronous operation which performs an allocation or dallocation on a particular execution context and returns a future to the complletion of the operation.","path":"managed-pointer/cpp-20/D0567R1.md","position":470,"original_position":470,"commit_id":"05a96ae95ea45b2d294f891d1b3addc1bbc34701","original_commit_id":"05a96ae95ea45b2d294f891d1b3addc1bbc34701","user":{"login":"Ruyk","id":3503397,"avatar_url":"https://avatars3.githubusercontent.com/u/3503397?v=3","gravatar_id":"","url":"https://api.github.com/users/Ruyk","html_url":"https://github.com/Ruyk","followers_url":"https://api.github.com/users/Ruyk/followers","following_url":"https://api.github.com/users/Ruyk/following{/other_user}","gists_url":"https://api.github.com/users/Ruyk/gists{/gist_id}","starred_url":"https://api.github.com/users/Ruyk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Ruyk/subscriptions","organizations_url":"https://api.github.com/users/Ruyk/orgs","repos_url":"https://api.github.com/users/Ruyk/repos","events_url":"https://api.github.com/users/Ruyk/events{/privacy}","received_events_url":"https://api.github.com/users/Ruyk/received_events","type":"User","site_admin":false},"body":"wishes -> wants\r\nasycnhronous -> asynchronous\r\nEach of which -> \"Each function\"\r\ncomplletion -> \"completion\"","created_at":"2017-06-07T12:17:33Z","updated_at":"2017-06-07T12:38:48Z","html_url":"https://github.com/codeplaysoftware/standards-proposals/pull/8#discussion_r120608784","pull_request_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8","_links":{"self":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/comments/120608784"},"html":{"href":"https://github.com/codeplaysoftware/standards-proposals/pull/8#discussion_r120608784"},"pull_request":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8"}}},"pull_request":{"url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8","id":123952656,"html_url":"https://github.com/codeplaysoftware/standards-proposals/pull/8","diff_url":"https://github.com/codeplaysoftware/standards-proposals/pull/8.diff","patch_url":"https://github.com/codeplaysoftware/standards-proposals/pull/8.patch","issue_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/8","number":8,"state":"open","locked":false,"title":"D0567D1 (working draft)","user":{"login":"AerialMantis","id":12399605,"avatar_url":"https://avatars0.githubusercontent.com/u/12399605?v=3","gravatar_id":"","url":"https://api.github.com/users/AerialMantis","html_url":"https://github.com/AerialMantis","followers_url":"https://api.github.com/users/AerialMantis/followers","following_url":"https://api.github.com/users/AerialMantis/following{/other_user}","gists_url":"https://api.github.com/users/AerialMantis/gists{/gist_id}","starred_url":"https://api.github.com/users/AerialMantis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AerialMantis/subscriptions","organizations_url":"https://api.github.com/users/AerialMantis/orgs","repos_url":"https://api.github.com/users/AerialMantis/repos","events_url":"https://api.github.com/users/AerialMantis/events{/privacy}","received_events_url":"https://api.github.com/users/AerialMantis/received_events","type":"User","site_admin":false},"body":"* Update proposal based on feedback.\r\n* See change list in document for full list of changes.","created_at":"2017-06-05T10:34:20Z","updated_at":"2017-06-07T12:38:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"0d6b4d26c886f47405bb48b2651e02ed6836fe10","assignee":{"login":"AerialMantis","id":12399605,"avatar_url":"https://avatars0.githubusercontent.com/u/12399605?v=3","gravatar_id":"","url":"https://api.github.com/users/AerialMantis","html_url":"https://github.com/AerialMantis","followers_url":"https://api.github.com/users/AerialMantis/followers","following_url":"https://api.github.com/users/AerialMantis/following{/other_user}","gists_url":"https://api.github.com/users/AerialMantis/gists{/gist_id}","starred_url":"https://api.github.com/users/AerialMantis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AerialMantis/subscriptions","organizations_url":"https://api.github.com/users/AerialMantis/orgs","repos_url":"https://api.github.com/users/AerialMantis/repos","events_url":"https://api.github.com/users/AerialMantis/events{/privacy}","received_events_url":"https://api.github.com/users/AerialMantis/received_events","type":"User","site_admin":false},"assignees":[{"login":"AerialMantis","id":12399605,"avatar_url":"https://avatars0.githubusercontent.com/u/12399605?v=3","gravatar_id":"","url":"https://api.github.com/users/AerialMantis","html_url":"https://github.com/AerialMantis","followers_url":"https://api.github.com/users/AerialMantis/followers","following_url":"https://api.github.com/users/AerialMantis/following{/other_user}","gists_url":"https://api.github.com/users/AerialMantis/gists{/gist_id}","starred_url":"https://api.github.com/users/AerialMantis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AerialMantis/subscriptions","organizations_url":"https://api.github.com/users/AerialMantis/orgs","repos_url":"https://api.github.com/users/AerialMantis/repos","events_url":"https://api.github.com/users/AerialMantis/events{/privacy}","received_events_url":"https://api.github.com/users/AerialMantis/received_events","type":"User","site_admin":false}],"requested_reviewers":[{"login":"fraggamuffin","id":6393929,"avatar_url":"https://avatars1.githubusercontent.com/u/6393929?v=3","gravatar_id":"","url":"https://api.github.com/users/fraggamuffin","html_url":"https://github.com/fraggamuffin","followers_url":"https://api.github.com/users/fraggamuffin/followers","following_url":"https://api.github.com/users/fraggamuffin/following{/other_user}","gists_url":"https://api.github.com/users/fraggamuffin/gists{/gist_id}","starred_url":"https://api.github.com/users/fraggamuffin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/fraggamuffin/subscriptions","organizations_url":"https://api.github.com/users/fraggamuffin/orgs","repos_url":"https://api.github.com/users/fraggamuffin/repos","events_url":"https://api.github.com/users/fraggamuffin/events{/privacy}","received_events_url":"https://api.github.com/users/fraggamuffin/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8/commits","review_comments_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8/comments","review_comment_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/comments{/number}","comments_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/8/comments","statuses_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/statuses/05a96ae95ea45b2d294f891d1b3addc1bbc34701","head":{"label":"AerialMantis:d0567r1-working-draft","ref":"d0567r1-working-draft","sha":"05a96ae95ea45b2d294f891d1b3addc1bbc34701","user":{"login":"AerialMantis","id":12399605,"avatar_url":"https://avatars0.githubusercontent.com/u/12399605?v=3","gravatar_id":"","url":"https://api.github.com/users/AerialMantis","html_url":"https://github.com/AerialMantis","followers_url":"https://api.github.com/users/AerialMantis/followers","following_url":"https://api.github.com/users/AerialMantis/following{/other_user}","gists_url":"https://api.github.com/users/AerialMantis/gists{/gist_id}","starred_url":"https://api.github.com/users/AerialMantis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AerialMantis/subscriptions","organizations_url":"https://api.github.com/users/AerialMantis/orgs","repos_url":"https://api.github.com/users/AerialMantis/repos","events_url":"https://api.github.com/users/AerialMantis/events{/privacy}","received_events_url":"https://api.github.com/users/AerialMantis/received_events","type":"User","site_admin":false},"repo":{"id":92937122,"name":"standards-proposals","full_name":"AerialMantis/standards-proposals","owner":{"login":"AerialMantis","id":12399605,"avatar_url":"https://avatars0.githubusercontent.com/u/12399605?v=3","gravatar_id":"","url":"https://api.github.com/users/AerialMantis","html_url":"https://github.com/AerialMantis","followers_url":"https://api.github.com/users/AerialMantis/followers","following_url":"https://api.github.com/users/AerialMantis/following{/other_user}","gists_url":"https://api.github.com/users/AerialMantis/gists{/gist_id}","starred_url":"https://api.github.com/users/AerialMantis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AerialMantis/subscriptions","organizations_url":"https://api.github.com/users/AerialMantis/orgs","repos_url":"https://api.github.com/users/AerialMantis/repos","events_url":"https://api.github.com/users/AerialMantis/events{/privacy}","received_events_url":"https://api.github.com/users/AerialMantis/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/AerialMantis/standards-proposals","description":"Repository for publicly sharing proposals in various standards groups","fork":true,"url":"https://api.github.com/repos/AerialMantis/standards-proposals","forks_url":"https://api.github.com/repos/AerialMantis/standards-proposals/forks","keys_url":"https://api.github.com/repos/AerialMantis/standards-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AerialMantis/standards-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AerialMantis/standards-proposals/teams","hooks_url":"https://api.github.com/repos/AerialMantis/standards-proposals/hooks","issue_events_url":"https://api.github.com/repos/AerialMantis/standards-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/AerialMantis/standards-proposals/events","assignees_url":"https://api.github.com/repos/AerialMantis/standards-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/AerialMantis/standards-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/AerialMantis/standards-proposals/tags","blobs_url":"https://api.github.com/repos/AerialMantis/standards-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AerialMantis/standards-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AerialMantis/standards-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/AerialMantis/standards-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AerialMantis/standards-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/AerialMantis/standards-proposals/languages","stargazers_url":"https://api.github.com/repos/AerialMantis/standards-proposals/stargazers","contributors_url":"https://api.github.com/repos/AerialMantis/standards-proposals/contributors","subscribers_url":"https://api.github.com/repos/AerialMantis/standards-proposals/subscribers","subscription_url":"https://api.github.com/repos/AerialMantis/standards-proposals/subscription","commits_url":"https://api.github.com/repos/AerialMantis/standards-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/AerialMantis/standards-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/AerialMantis/standards-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/AerialMantis/standards-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/AerialMantis/standards-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/AerialMantis/standards-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AerialMantis/standards-proposals/merges","archive_url":"https://api.github.com/repos/AerialMantis/standards-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AerialMantis/standards-proposals/downloads","issues_url":"https://api.github.com/repos/AerialMantis/standards-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/AerialMantis/standards-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/AerialMantis/standards-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/AerialMantis/standards-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AerialMantis/standards-proposals/labels{/name}","releases_url":"https://api.github.com/repos/AerialMantis/standards-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/AerialMantis/standards-proposals/deployments","created_at":"2017-05-31T10:59:23Z","updated_at":"2017-05-31T10:59:24Z","pushed_at":"2017-06-05T10:33:53Z","git_url":"git://github.com/AerialMantis/standards-proposals.git","ssh_url":"git@github.com:AerialMantis/standards-proposals.git","clone_url":"https://github.com/AerialMantis/standards-proposals.git","svn_url":"https://github.com/AerialMantis/standards-proposals","homepage":null,"size":70,"stargazers_count":0,"watchers_count":0,"language":"Makefile","has_issues":false,"has_projects":true,"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":0,"default_branch":"master"}},"base":{"label":"codeplaysoftware:master","ref":"master","sha":"fdbe0064f7d008066bb4ecaed2ac2aa5411bab18","user":{"login":"codeplaysoftware","id":7440916,"avatar_url":"https://avatars3.githubusercontent.com/u/7440916?v=3","gravatar_id":"","url":"https://api.github.com/users/codeplaysoftware","html_url":"https://github.com/codeplaysoftware","followers_url":"https://api.github.com/users/codeplaysoftware/followers","following_url":"https://api.github.com/users/codeplaysoftware/following{/other_user}","gists_url":"https://api.github.com/users/codeplaysoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/codeplaysoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codeplaysoftware/subscriptions","organizations_url":"https://api.github.com/users/codeplaysoftware/orgs","repos_url":"https://api.github.com/users/codeplaysoftware/repos","events_url":"https://api.github.com/users/codeplaysoftware/events{/privacy}","received_events_url":"https://api.github.com/users/codeplaysoftware/received_events","type":"Organization","site_admin":false},"repo":{"id":71551822,"name":"standards-proposals","full_name":"codeplaysoftware/standards-proposals","owner":{"login":"codeplaysoftware","id":7440916,"avatar_url":"https://avatars3.githubusercontent.com/u/7440916?v=3","gravatar_id":"","url":"https://api.github.com/users/codeplaysoftware","html_url":"https://github.com/codeplaysoftware","followers_url":"https://api.github.com/users/codeplaysoftware/followers","following_url":"https://api.github.com/users/codeplaysoftware/following{/other_user}","gists_url":"https://api.github.com/users/codeplaysoftware/gists{/gist_id}","starred_url":"https://api.github.com/users/codeplaysoftware/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codeplaysoftware/subscriptions","organizations_url":"https://api.github.com/users/codeplaysoftware/orgs","repos_url":"https://api.github.com/users/codeplaysoftware/repos","events_url":"https://api.github.com/users/codeplaysoftware/events{/privacy}","received_events_url":"https://api.github.com/users/codeplaysoftware/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codeplaysoftware/standards-proposals","description":"Repository for publicly sharing proposals in various standards groups","fork":false,"url":"https://api.github.com/repos/codeplaysoftware/standards-proposals","forks_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/forks","keys_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/teams","hooks_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/hooks","issue_events_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/events{/number}","events_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/events","assignees_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/assignees{/user}","branches_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/branches{/branch}","tags_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/tags","blobs_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/git/refs{/sha}","trees_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/statuses/{sha}","languages_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/languages","stargazers_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/stargazers","contributors_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/contributors","subscribers_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/subscribers","subscription_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/subscription","commits_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/commits{/sha}","git_commits_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/git/commits{/sha}","comments_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/comments{/number}","issue_comment_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/comments{/number}","contents_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/contents/{+path}","compare_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/merges","archive_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/downloads","issues_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues{/number}","pulls_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls{/number}","milestones_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/milestones{/number}","notifications_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/labels{/name}","releases_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/releases{/id}","deployments_url":"https://api.github.com/repos/codeplaysoftware/standards-proposals/deployments","created_at":"2016-10-21T09:38:17Z","updated_at":"2017-01-31T19:36:14Z","pushed_at":"2017-06-05T10:34:21Z","git_url":"git://github.com/codeplaysoftware/standards-proposals.git","ssh_url":"git@github.com:codeplaysoftware/standards-proposals.git","clone_url":"https://github.com/codeplaysoftware/standards-proposals.git","svn_url":"https://github.com/codeplaysoftware/standards-proposals","homepage":null,"size":56,"stargazers_count":3,"watchers_count":3,"language":"Makefile","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"open_issues_count":2,"forks":3,"open_issues":2,"watchers":3,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8"},"html":{"href":"https://github.com/codeplaysoftware/standards-proposals/pull/8"},"issue":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/8"},"comments":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/issues/8/comments"},"review_comments":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8/comments"},"review_comment":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/pulls/8/commits"},"statuses":{"href":"https://api.github.com/repos/codeplaysoftware/standards-proposals/statuses/05a96ae95ea45b2d294f891d1b3addc1bbc34701"}}}}
{"actor":{"display_login":"Ruyk"}}