• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019  Facebook, Inc.
3  *
4  *  This is part of HarfBuzz, a text shaping library.
5  *
6  * Permission is hereby granted, without written agreement and without
7  * license or royalty fees, to use, copy, modify, and distribute this
8  * software and its documentation for any purpose, provided that the
9  * above copyright notice and the following two paragraphs appear in
10  * all copies of this software.
11  *
12  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
16  * DAMAGE.
17  *
18  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
23  *
24  * Facebook Author(s): Behdad Esfahbod
25  */
26 
27 #ifndef HB_POOL_HH
28 #define HB_POOL_HH
29 
30 #include "hb.hh"
31 
32 /* Memory pool for persistent allocation of small objects. */
33 
34 template <typename T, unsigned ChunkLen = 16>
35 struct hb_pool_t
36 {
hb_pool_thb_pool_t37   hb_pool_t () : next (nullptr) {}
~hb_pool_thb_pool_t38   ~hb_pool_t () { fini (); }
39 
finihb_pool_t40   void fini ()
41   {
42     next = nullptr;
43 
44     + hb_iter (chunks)
45     | hb_apply ([] (chunk_t *_) { ::free (_); })
46     ;
47 
48     chunks.fini ();
49   }
50 
allochb_pool_t51   T* alloc ()
52   {
53     if (unlikely (!next))
54     {
55       if (unlikely (!chunks.alloc (chunks.length + 1))) return nullptr;
56       chunk_t *chunk = (chunk_t *) calloc (1, sizeof (chunk_t));
57       if (unlikely (!chunk)) return nullptr;
58       chunks.push (chunk);
59       next = chunk->thread ();
60     }
61 
62     T* obj = next;
63     next = * ((T**) next);
64 
65     memset (obj, 0, sizeof (T));
66 
67     return obj;
68   }
69 
freehb_pool_t70   void free (T* obj)
71   {
72     * (T**) obj = next;
73     next = obj;
74   }
75 
76   private:
77 
78   static_assert (ChunkLen > 1, "");
79   static_assert (sizeof (T) >= sizeof (void *), "");
80   static_assert (alignof (T) % alignof (void *) == 0, "");
81 
82   struct chunk_t
83   {
threadhb_pool_t::chunk_t84     T* thread ()
85     {
86       for (unsigned i = 0; i < ARRAY_LENGTH (arrayZ) - 1; i++)
87 	* (T**) &arrayZ[i] = &arrayZ[i + 1];
88 
89       * (T**) &arrayZ[ARRAY_LENGTH (arrayZ) - 1] = nullptr;
90 
91       return arrayZ;
92     }
93 
94     T arrayZ[ChunkLen];
95   };
96 
97   T* next;
98   hb_vector_t<chunk_t *> chunks;
99 };
100 
101 
102 #endif /* HB_POOL_HH */
103