ViennaCL - The Vienna Computing Library  1.5.1
viennacl/ocl/handle.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_OCL_HANDLE_HPP_
00002 #define VIENNACL_OCL_HANDLE_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #ifdef __APPLE__
00026 #include <OpenCL/cl.h>
00027 #else
00028 #include <CL/cl.h>
00029 #endif
00030 
00031 #include <assert.h>
00032 #include <string>
00033 #include <iostream>
00034 #include "viennacl/ocl/forwards.h"
00035 #include "viennacl/ocl/error.hpp"
00036 
00037 namespace viennacl
00038 {
00039   namespace ocl
00040   {
00044     template<class OCL_TYPE>
00045     class handle_inc_dec_helper
00046     {
00047       typedef typename OCL_TYPE::ERROR_TEMPLATE_ARGUMENT_FOR_CLASS_INVALID   ErrorType;
00048     };
00049 
00051     //cl_mem:
00052     template <>
00053     struct handle_inc_dec_helper<cl_mem>
00054     {
00055       static void inc(cl_mem & something)
00056       {
00057         cl_int err = clRetainMemObject(something);
00058         VIENNACL_ERR_CHECK(err);
00059       }
00060 
00061       static void dec(cl_mem & something)
00062       {
00063         #ifndef __APPLE__
00064         cl_int err = clReleaseMemObject(something);
00065         VIENNACL_ERR_CHECK(err);
00066         #endif
00067       }
00068     };
00069 
00070     //cl_program:
00071     template <>
00072     struct handle_inc_dec_helper<cl_program>
00073     {
00074       static void inc(cl_program & something)
00075       {
00076         cl_int err = clRetainProgram(something);
00077         VIENNACL_ERR_CHECK(err);
00078       }
00079 
00080       static void dec(cl_program & something)
00081       {
00082         #ifndef __APPLE__
00083         cl_int err = clReleaseProgram(something);
00084         VIENNACL_ERR_CHECK(err);
00085         #endif
00086       }
00087     };
00088 
00089     //cl_kernel:
00090     template <>
00091     struct handle_inc_dec_helper<cl_kernel>
00092     {
00093       static void inc(cl_kernel & something)
00094       {
00095         cl_int err = clRetainKernel(something);
00096         VIENNACL_ERR_CHECK(err);
00097       }
00098 
00099       static void dec(cl_kernel & something)
00100       {
00101         #ifndef __APPLE__
00102         cl_int err = clReleaseKernel(something);
00103         VIENNACL_ERR_CHECK(err);
00104         #endif
00105       }
00106     };
00107 
00108     //cl_command_queue:
00109     template <>
00110     struct handle_inc_dec_helper<cl_command_queue>
00111     {
00112       static void inc(cl_command_queue & something)
00113       {
00114         cl_int err = clRetainCommandQueue(something);
00115         VIENNACL_ERR_CHECK(err);
00116       }
00117 
00118       static void dec(cl_command_queue & something)
00119       {
00120         #ifndef __APPLE__
00121         cl_int err = clReleaseCommandQueue(something);
00122         VIENNACL_ERR_CHECK(err);
00123         #endif
00124       }
00125     };
00126 
00127     //cl_context:
00128     template <>
00129     struct handle_inc_dec_helper<cl_context>
00130     {
00131       static void inc(cl_context & something)
00132       {
00133         cl_int err = clRetainContext(something);
00134         VIENNACL_ERR_CHECK(err);
00135       }
00136 
00137       static void dec(cl_context & something)
00138       {
00139         #ifndef __APPLE__
00140         cl_int err = clReleaseContext(something);
00141         VIENNACL_ERR_CHECK(err);
00142         #endif
00143       }
00144     };
00148     template<class OCL_TYPE>
00149     class handle
00150     {
00151       public:
00152         handle() : h_(0), p_context_(NULL) {}
00153         handle(const OCL_TYPE & something, viennacl::ocl::context const & c) : h_(something), p_context_(&c) {}
00154         handle(const handle & other) : h_(other.h_), p_context_(other.p_context_) { if (h_ != 0) inc(); }
00155         ~handle() { if (h_ != 0) dec(); }
00156 
00158         handle & operator=(const handle & other)
00159         {
00160           if (h_ != 0)
00161             dec();
00162           h_         = other.h_;
00163           p_context_ = other.p_context_;
00164           inc();
00165           return *this;
00166         }
00167 
00169         handle & operator=(const OCL_TYPE & something)
00170         {
00171           if (h_ != 0) dec();
00172           h_ = something;
00173           return *this;
00174         }
00175 
00177         handle & operator=(std::pair<OCL_TYPE, cl_context> p)
00178         {
00179           if (h_ != 0) dec();
00180           h_         = p.first;
00181           p_context_ = p.second;
00182           return *this;
00183         }
00184 
00185 
00187         operator OCL_TYPE() const { return h_; }
00188 
00189         const OCL_TYPE & get() const { return h_; }
00190 
00191         viennacl::ocl::context const & context() const
00192         {
00193           assert(p_context_ != NULL && bool("Logic error: Accessing dangling context from handle."));
00194           return *p_context_;
00195         }
00196         void context(viennacl::ocl::context const & c) { p_context_ = &c; }
00197 
00198 
00200         handle & swap(handle & other)
00201         {
00202           OCL_TYPE tmp = other.h_;
00203           other.h_ = this->h_;
00204           this->h_ = tmp;
00205 
00206           viennacl::ocl::context const * tmp2 = other.p_context_;
00207           other.p_context_ = this->p_context_;
00208           this->p_context_ = tmp2;
00209 
00210           return *this;
00211         }
00212 
00214         void inc() { handle_inc_dec_helper<OCL_TYPE>::inc(h_); }
00216         void dec() { handle_inc_dec_helper<OCL_TYPE>::dec(h_); }
00217       private:
00218         OCL_TYPE h_;
00219         viennacl::ocl::context const * p_context_;
00220     };
00221 
00222 
00223   } //namespace ocl
00224 } //namespace viennacl
00225 
00226 #endif