1/*******************************************************************************
2* Copyright 2022 Intel Corporation
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*******************************************************************************/
16
17#ifndef COMMON_RESOURCE_HPP
18#define COMMON_RESOURCE_HPP
19
20#include <assert.h>
21#include <unordered_map>
22
23#include "c_types_map.hpp"
24#include "oneapi/dnnl/dnnl.h"
25
26namespace dnnl {
27namespace impl {
28
29// The resource_t abstraction is a base class for all resource classes.
30// Those are responsible for holding a part of a primitive implementation that
31// cannot be stored in the primitive cache as part of the implementation.
32// Currently, there are two such things:
33// 1. Any memory (memory_t, memory_storage_t, etc...), because it contains
34// an engine.
35// 2. (for GPU only) compiled kernels, because they are context dependent.
36//
37// The idea is that each primitive implementation should be able to create
38// a resource and put there everything it needs to run, which cannot be stored
39// in the cache as part of the primitive implementation. To create the resource
40// each primitive implementation can override a function `create_resource`.
41//
42// This abstraction takes ownership of all content it holds hence it should be
43// responsible for destroying it as well.
44struct resource_t : public c_compatible {
45 virtual ~resource_t() = default;
46};
47
48// The resource_mapper_t is an abstraction for holding resources for
49// a particular primitive implementation and providing corresponding mapping.
50//
51// Interacting with the mapper happens in two steps:
52// 1. Initialization. Each derived from impl::primitive_t class may define
53// `create_resource` member function that is responsible for creating a
54// certain derived from resource_t object and filling it with some content,
55// e.g. memory for scales, OpenCL kernels etc...
56// 2. Passing it to the execution function which extracts needed resources and
57// uses them at execution time. The mapper is passed to the execution function
58// with the execution context.
59//
60// The resource_mapper_t takes ownership of all resources hence it should be
61// responsible for destroying them as well.
62struct primitive_t;
63struct resource_mapper_t {
64 using key_t = const primitive_t;
65 using mapped_t = std::unique_ptr<resource_t>;
66
67 resource_mapper_t() = default;
68
69 bool has_resource(const primitive_t *p) const {
70 return primitive_to_resource_.count(p);
71 }
72
73 void add(key_t *p, mapped_t &&r) {
74 assert(primitive_to_resource_.count(p) == 0);
75 primitive_to_resource_.emplace(p, std::move(r));
76 }
77
78 template <typename T>
79 const T *get(key_t *p) const {
80 assert(primitive_to_resource_.count(p));
81 return utils::downcast<T *>(primitive_to_resource_.at(p).get());
82 }
83
84 DNNL_DISALLOW_COPY_AND_ASSIGN(resource_mapper_t);
85
86private:
87 std::unordered_map<key_t *, mapped_t> primitive_to_resource_;
88};
89
90} // namespace impl
91} // namespace dnnl
92
93#endif
94