IVGCVSW-2056+IVGCVSW-2064 : move ClContextControl to the ClBackend

* add IBackendContext interface
* add ClBackendContext implementation

Change-Id: I13e4d12b73d4c7775069587675276f7cee7d630b
diff --git a/src/backends/cl/ClBackendContext.cpp b/src/backends/cl/ClBackendContext.cpp
new file mode 100644
index 0000000..a2c1b87
--- /dev/null
+++ b/src/backends/cl/ClBackendContext.cpp
@@ -0,0 +1,113 @@
+//
+// Copyright © 2017 Arm Ltd. All rights reserved.
+// SPDX-License-Identifier: MIT
+//
+
+#include "ClBackendContext.hpp"
+#include "ClContextControl.hpp"
+
+#include <boost/log/trivial.hpp>
+
+#ifdef ARMCOMPUTECL_ENABLED
+#include <arm_compute/core/CL/OpenCL.h>
+#include <arm_compute/core/CL/CLKernelLibrary.h>
+#include <arm_compute/runtime/CL/CLScheduler.h>
+#endif
+
+namespace armnn
+{
+
+struct ClBackendContext::ClContextControlWrapper
+{
+    ClContextControlWrapper(IGpuAccTunedParameters* clTunedParameters,
+                            bool profilingEnabled)
+        : m_ClContextControl(clTunedParameters, profilingEnabled)
+    {}
+
+    bool Sync()
+    {
+#ifdef ARMCOMPUTECL_ENABLED
+        if (arm_compute::CLScheduler::get().context()() != NULL)
+        {
+            // Waits for all queued CL requests to finish before unloading the network they may be using.
+            try
+            {
+                // Coverity fix: arm_compute::CLScheduler::sync() may throw an exception of type cl::Error.
+                arm_compute::CLScheduler::get().sync();
+            }
+            catch (const cl::Error&)
+            {
+                BOOST_LOG_TRIVIAL(warning) << "WARNING: Runtime::UnloadNetwork(): an error occurred while waiting for "
+                                            "the queued CL requests to finish";
+                return false;
+            }
+        }
+#endif
+        return true;
+    }
+
+    void ClearClCache()
+    {
+#ifdef ARMCOMPUTECL_ENABLED
+        if (arm_compute::CLScheduler::get().context()() != NULL)
+        {
+            // There are no loaded networks left, so clear the CL cache to free up memory
+            m_ClContextControl.ClearClCache();
+        }
+#endif
+    }
+
+
+    ClContextControl m_ClContextControl;
+};
+
+
+ClBackendContext::ClBackendContext(const IRuntime::CreationOptions& options)
+    : IBackendContext(options)
+    , m_ClContextControlWrapper(
+        std::make_unique<ClContextControlWrapper>(options.m_GpuAccTunedParameters.get(),
+                                                  options.m_EnableGpuProfiling))
+{
+}
+
+bool ClBackendContext::BeforeLoadNetwork(NetworkId)
+{
+    return true;
+}
+
+bool ClBackendContext::AfterLoadNetwork(NetworkId networkId)
+{
+    {
+        std::lock_guard<std::mutex> lockGuard(m_Mutex);
+        m_NetworkIds.insert(networkId);
+    }
+    return true;
+}
+
+bool ClBackendContext::BeforeUnloadNetwork(NetworkId)
+{
+    return m_ClContextControlWrapper->Sync();
+}
+
+bool ClBackendContext::AfterUnloadNetwork(NetworkId networkId)
+{
+    bool clearCache = false;
+    {
+        std::lock_guard<std::mutex> lockGuard(m_Mutex);
+        m_NetworkIds.erase(networkId);
+        clearCache = m_NetworkIds.empty();
+    }
+
+    if (clearCache)
+    {
+        m_ClContextControlWrapper->ClearClCache();
+    }
+
+    return true;
+}
+
+ClBackendContext::~ClBackendContext()
+{
+}
+
+} // namespace armnn
\ No newline at end of file