Enhanced SIM for E2AP v1 for TS UC
[sim/e2-interface.git] / e2sim / e2apv1sim / src / ASN1 / asn / chunked_allocator.hpp
1 #pragma once
2
3 /*******************************************************************************
4 *
5 *   Copyright (c) 2019 AT&T Intellectual Property.
6 *   Copyright (c) 2018-2019 Nokia.
7 *
8 *   Licensed under the Apache License, Version 2.0 (the "License");
9 *   you may not use this file except in compliance with the License.
10 *   You may obtain a copy of the License at
11 *
12 *       http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *   Unless required by applicable law or agreed to in writing, software
15 *   distributed under the License is distributed on an "AS IS" BASIS,
16 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *   See the License for the specific language governing permissions and
18 *   limitations under the License.
19 *
20 *******************************************************************************/
21
22 // Standard Includes: ANSI C/C++, MSA, and Third-Party Libraries
23 #include <cstdint>
24 #include <new> //std::bad_alloc
25 #include <array>
26 #include <list>
27
28 // Platform Includes: Platform specific classes, functions, and libraries
29
30 // Local Includes: Application specific classes, functions, and libraries
31
32 namespace asn {
33
34 template <class ALLOC>
35 class chunked_allocator
36 {
37 public:
38         using allocator_t = ALLOC;
39
40         chunked_allocator()
41         {
42                 put_chunk(new_chunk());
43         }
44
45         template<class TSEQ>
46         decltype(auto) emplace_back(TSEQ& v)
47         {
48                 try
49                 {
50                         return v.emplace_back(m_allocator);
51                 }
52                 catch (std::bad_alloc const&)
53                 {
54                         put_chunk(new_chunk());
55                         return v.emplace_back(m_allocator);
56                 }
57         }
58
59         uint8_t* alloc_bytes(std::size_t sz)
60         {
61                 //TODO: unify allocation: now it returns nullptr instead of throw!
62                 auto* ret = m_allocator.alloc_bytes(sz);
63                 if (!ret)
64                 {
65                         put_chunk(new_chunk());
66                         ret = m_allocator.alloc_bytes(sz);
67                 }
68                 return ret;
69         }
70
71 private:
72         static constexpr std::size_t CHUNK_SIZE = 32*1024;
73         using chunk_t = std::array<uint8_t, CHUNK_SIZE>;
74         using chunks_t = std::list<chunk_t>;
75
76         chunk_t& new_chunk()        { return m_chunks.emplace_back(); }
77         void put_chunk(chunk_t& c)  { m_allocator.reset(c.data(), c.size()); }
78
79
80         allocator_t m_allocator;
81         chunks_t    m_chunks;
82 };
83
84 }       //end: namespace asn