Add create_unique_with_deleter
authorRoland Schulz <roland.schulz@intel.com>
Fri, 25 Nov 2016 06:04:08 +0000 (22:04 -0800)
committerRoland Schulz <roland.schulz@intel.com>
Thu, 15 Dec 2016 21:13:42 +0000 (22:13 +0100)
A more flexible alternative to unique_cptr. Takes also
non-void deleter functions or lambdas as argument.

Change-Id: I25c1d7d9ed63556cc42230f3da578dc449116d78

src/gromacs/gpu_utils/ocl_caching.cpp
src/gromacs/utility/unique_cptr.h

index a5046265e88d736bf3c78316026e7ccea2b72d14..d6016671ef17214787877cf63c9d018f6af3cec3 100644 (file)
@@ -68,21 +68,6 @@ namespace gmx
 namespace ocl
 {
 
-/*! \brief RAII helper to use with unique_cptr
- *
- * Can't use fclose because the template requires a function that
- * returns void.
- *
- * \todo Either generalise unique_cptr somehow, or (better) make
- * general infrastructure for reading and writing binary lumps.
- * Neither of these is a priority while JIT caching is inactive.
- */
-static void fclose_wrapper(FILE *fp)
-{
-    assert(fp != NULL);
-    fclose(fp);
-}
-
 std::string makeBinaryCacheFilename(const std::string &kernelFilename,
                                     cl_device_id       deviceId)
 {
@@ -119,22 +104,21 @@ makeProgramFromCache(const std::string &filename,
                      cl_device_id       deviceId)
 {
     // TODO all this file reading stuff should become gmx::BinaryReader
-    FILE *f = fopen(filename.c_str(), "rb");
-    const unique_cptr<FILE, fclose_wrapper> fileGuard(f);
+    const auto f = create_unique_with_deleter(fopen(filename.c_str(), "rb"), fclose);
     if (!f)
     {
         GMX_THROW(FileIOError("Failed to open binary cache file " + filename));
     }
 
     // TODO more stdio error handling
-    fseek(f, 0, SEEK_END);
+    fseek(f.get(), 0, SEEK_END);
     unsigned char             *binary;
     unique_cptr<unsigned char> binaryGuard;
-    size_t                     fileSize = ftell(f);
+    size_t                     fileSize = ftell(f.get());
     snew(binary, fileSize);
     binaryGuard.reset(binary);
-    fseek(f, 0, SEEK_SET);
-    size_t readCount = fread(binary, 1, fileSize, f);
+    fseek(f.get(), 0, SEEK_SET);
+    size_t readCount = fread(binary, 1, fileSize, f.get());
 
     if (readCount != fileSize)
     {
@@ -186,14 +170,13 @@ writeBinaryToCache(cl_program program, const std::string &filename)
         GMX_THROW(InternalError("Could not get OpenCL program binary, error was " + ocl_get_error_string(cl_error)));
     }
 
-    FILE *f = fopen(filename.c_str(), "wb");
-    const unique_cptr<FILE, fclose_wrapper> fileGuard(f);
+    const auto f = create_unique_with_deleter(fopen(filename.c_str(), "wb"), fclose);
     if (!f)
     {
         GMX_THROW(FileIOError("Failed to open binary cache file " + filename));
     }
 
-    fwrite(binary, 1, fileSize, f);
+    fwrite(binary, 1, fileSize, f.get());
 }
 
 } // namespace
index 41016f7492fb564ef25a4b8c93a300a27356406d..058abfa12422091604d877b2e8e33e181b1a8f27 100644 (file)
@@ -64,13 +64,18 @@ struct functor_wrapper {
     void operator()(T* t) { D(t); }
 };
 
-//! unique_ptr which takes function pointer as template argument
+//! unique_ptr which takes function pointer (has to return void) as template argument
 template<typename T, void D(T *) = sfree_wrapper>
 using unique_cptr                = std::unique_ptr<T, functor_wrapper<T, D> >;
 
 //! Simple guard which calls sfree. See unique_cptr for details.
 typedef unique_cptr<void> sfree_guard;
 
+
+//! Create unique_ptr with any deleter function or lambda
+template<typename T, typename D>
+std::unique_ptr<T, D> create_unique_with_deleter(T *t, D d) { return std::unique_ptr<T, D>(t, d); }
+
 }      // namespace gmx
 
 #endif