Line data Source code
1 : /* cairo - a vector graphics library with display and print output
2 : *
3 : * Copyright © 2009 Chris Wilson
4 : *
5 : * This library is free software; you can redistribute it and/or
6 : * modify it either under the terms of the GNU Lesser General Public
7 : * License version 2.1 as published by the Free Software Foundation
8 : * (the "LGPL") or, at your option, under the terms of the Mozilla
9 : * Public License Version 1.1 (the "MPL"). If you do not alter this
10 : * notice, a recipient may use your version of this file under either
11 : * the MPL or the LGPL.
12 : *
13 : * You should have received a copy of the LGPL along with this library
14 : * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 : * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 : * You should have received a copy of the MPL along with this library
17 : * in the file COPYING-MPL-1.1
18 : *
19 : * The contents of this file are subject to the Mozilla Public License
20 : * Version 1.1 (the "License"); you may not use this file except in
21 : * compliance with the License. You may obtain a copy of the License at
22 : * http://www.mozilla.org/MPL/
23 : *
24 : * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 : * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 : * the specific language governing rights and limitations.
27 : *
28 : * The Original Code is the cairo graphics library.
29 : *
30 : * The Initial Developer of the Original Code is University of Southern
31 : * California.
32 : *
33 : * Contributor(s):
34 : * Chris Wilson <chris@chris-wilson.co.uk>
35 : */
36 :
37 : #ifndef CAIRO_FREED_POOL_H
38 : #define CAIRO_FREED_POOL_H
39 :
40 : #include "cairoint.h"
41 : #include "cairo-atomic-private.h"
42 :
43 : #if HAS_ATOMIC_OPS
44 : /* Keep a stash of recently freed clip_paths, since we need to
45 : * reallocate them frequently.
46 : */
47 : #define MAX_FREED_POOL_SIZE 4
48 : typedef struct {
49 : void *pool[MAX_FREED_POOL_SIZE];
50 : cairo_atomic_int_t top;
51 : } freed_pool_t;
52 :
53 : static cairo_always_inline void *
54 : _atomic_fetch (void **slot)
55 : {
56 : void *ptr;
57 :
58 : do {
59 0 : ptr = _cairo_atomic_ptr_get (slot);
60 0 : } while (! _cairo_atomic_ptr_cmpxchg (slot, ptr, NULL));
61 :
62 0 : return ptr;
63 : }
64 :
65 : static cairo_always_inline cairo_bool_t
66 : _atomic_store (void **slot, void *ptr)
67 : {
68 0 : return _cairo_atomic_ptr_cmpxchg (slot, NULL, ptr);
69 : }
70 :
71 : cairo_private void *
72 : _freed_pool_get_search (freed_pool_t *pool);
73 :
74 : static inline void *
75 0 : _freed_pool_get (freed_pool_t *pool)
76 : {
77 : void *ptr;
78 : int i;
79 :
80 0 : i = _cairo_atomic_int_get_relaxed (&pool->top) - 1;
81 0 : if (i < 0)
82 0 : i = 0;
83 :
84 0 : ptr = _atomic_fetch (&pool->pool[i]);
85 0 : if (likely (ptr != NULL)) {
86 0 : _cairo_atomic_int_set_relaxed (&pool->top, i);
87 0 : return ptr;
88 : }
89 :
90 : /* either empty or contended */
91 0 : return _freed_pool_get_search (pool);
92 : }
93 :
94 : cairo_private void
95 : _freed_pool_put_search (freed_pool_t *pool, void *ptr);
96 :
97 : static inline void
98 0 : _freed_pool_put (freed_pool_t *pool, void *ptr)
99 : {
100 : int i;
101 :
102 0 : i = _cairo_atomic_int_get_relaxed (&pool->top);
103 0 : if (likely (i < ARRAY_LENGTH (pool->pool) &&
104 : _atomic_store (&pool->pool[i], ptr)))
105 : {
106 0 : _cairo_atomic_int_set_relaxed (&pool->top, i + 1);
107 0 : return;
108 : }
109 :
110 : /* either full or contended */
111 0 : _freed_pool_put_search (pool, ptr);
112 : }
113 :
114 : cairo_private void
115 : _freed_pool_reset (freed_pool_t *pool);
116 :
117 : #define HAS_FREED_POOL 1
118 :
119 : #else
120 :
121 : typedef int freed_pool_t;
122 :
123 : #define _freed_pool_get(pool) NULL
124 : #define _freed_pool_put(pool, ptr) free(ptr)
125 : #define _freed_pool_reset(ptr)
126 :
127 : #endif
128 :
129 : #endif /* CAIRO_FREED_POOL_PRIVATE_H */
|