* improved runtime kernel reloading:
   * moved to a shared_ptr/weak_ptr model for opencl kernel objects
   -> only weak_ptrs will be returned from the opencl class, and only those should be stored outside of this class
   -> if you need to access a kernel_objects data, you need to make a shared_ptr out of the weak_ptr (.lock()) + of course check, if the kernel still exists
   -> in normal use cases this shouldn't be necessary, since all kernel execution and handling is done indirectly through the opencl class and identifiers
   -> runtime kernel reloading works as expected now