Major refactoring

The goal of this pull request is refactoring two sections. One is the removal of the ComputeContext, since it had a tendency to be used everywhere and people would just peak into it. The reason for this was to give the API user more direct control over which queues were doing the work, and how things were synchronized. Abstracting the read() and writes() for example in the vector or unique class forces the api user to wait before fetching data. 

The command queue, the device, and the context have all been flushed out with some of the functionality that was only reserved for the command queue at one time.

Since it is pretty annoying to initialize opencl without the ComputeContext, a utility function is added that gives the user a context, device, and command queue.

The memory subsystem needed to be rework to. My goal was to allow the user to define how to read and write data into the opencl runtime allowing for them to do simple transfers like a vector read or write. Or more complicated things like reading the header to determine the size of the object before reading it into the host's memory space.

Buffer is also rework to allow for user implementations. And they are now typed to avoid unsafe conditions and better type inference.

There is an addition of a 2D/3D array type, which was one of the motivations for the rework to begin with.