summaryrefslogtreecommitdiff
path: root/src/lib/eina/eina_cow.h
blob: 10cb34d28dbf6ac985e736ba5f210c14f3e370a9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/* EINA - EFL data type library
 * Copyright (C) 2013 Cedric Bail
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library;
 * if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef EINA_COW_H_
#define EINA_COW_H_


/**
 * @addtogroup Eina_Tools_Group Tools
 *
 * @{
 */

/**
 * @defgroup Eina_Cow_Group Lock
 *
 * @brief These functions provide some helper for a pseudo Copy On Write mechanism.
 *
 * Eina_Cow will return const memory pointer to some default value that you will
 * be able to change only by requesting a writable pointer. Later on a garbage collector
 * can come online and try to merge back some of those pointer.
 *
 * @since 1.8.0
 *
 * @{
 */

/**
 * @typedef Eina_Cow
 * Type for Eina_Cow pool
 */
typedef struct _Eina_Cow Eina_Cow;
/**
 * @typedef Eina_Cow_Data
 * Type of the returned pointer to simplify some reading.
 */
typedef void Eina_Cow_Data;

/**
 * @brief Instantiate a new Eina_Cow pool.
 *
 * @param name The name of this pool, used for debug.
 * @param struct_size The size of the object from this pool.
 * @param step How many object to allocate when the pool get empty.
 * @param default_value The default value returned by this pool.
 * @param gc Is it possible to run the garbage collection on this pool.
 * @return a valid new Eina_Cow or @c NULL on error.
 */
EAPI Eina_Cow *eina_cow_add(const char *name, unsigned int struct_size, unsigned int step, const void *default_value, Eina_Bool gc) EINA_WARN_UNUSED_RESULT;

/**
 * @brief Destroy an Eina_Cow pool and all the allocated memory
 *
 * @param cow The pool to destroy
 */
EAPI void eina_cow_del(Eina_Cow *cow);

/**
 * @brief Return a initialized pointer to the pool.
 * @param cow The pool to take things from.
 */
EAPI const Eina_Cow_Data *eina_cow_alloc(Eina_Cow *cow) EINA_WARN_UNUSED_RESULT;

/**
 * @brief Free a pointer from the pool.
 * @param cow The pool to gave back memory to.
 * @param data The data to give back.
 *
 * @note To simplify the caller code *data will point to the default
 * read only state after the call to this function.
 */
EAPI void eina_cow_free(Eina_Cow *cow, const Eina_Cow_Data **data);

/**
 * @brief Get a writable pointer from a const pointer.
 * @param cow The pool the pointer come from.
 * @param src The pointer you want to write to.
 *
 * NOTE: this function is not thread safe, be careful.
 */
EAPI void *eina_cow_write(Eina_Cow *cow,
			  const Eina_Cow_Data * const *src) EINA_WARN_UNUSED_RESULT;
/**
 * @brief Set back a pointer into read only.
 * @param cow The pool the pointer come from.
 * @param src The read only version of the pointer.
 * @param data The pointer to which data where written to.
 *
 * NOTE: this function is not thread safe, be careful.
 */
EAPI void eina_cow_done(Eina_Cow *cow,
			const Eina_Cow_Data * const *dst,
			const void *data,
			Eina_Bool needed_gc);
/**
 * @brief Make the destination contain the same thing as the source pointer.
 * @param cow The pool the pointers come from.
 * @param dst The destination to update.
 * @param src The source of information to copy.
 */
EAPI void eina_cow_memcpy(Eina_Cow *cow,
			  const Eina_Cow_Data * const *dst,
			  const Eina_Cow_Data *src);

/**
 * @brief Try to find entry that do have the same content and update them.
 * @param cow The cow to try to compact.
 * @return EINA_TRUE if something was compacted, EINA_FALSE if nothing was.
 *
 * There is no guaranty in the time it will require, but should remain low.
 * It does run a hash function on all possible common structure trying to
 * find the one that match and merge then into one pointer.
 */
EAPI Eina_Bool eina_cow_gc(Eina_Cow *cow);

/**
 * @def EINA_COW_WRITE_BEGIN
 * @brief This macro setup a writable pointer from a const one.
 * @param Cow The Eina_Cow where the const pointer come from.
 * @param Read The const pointer to get a writable handler from.
 * @param Write_Type The type of the pointer you want to write to.
 * @param Write The name of the variable where to put the writeable pointer to.
 * @since 1.8.0
 *
 * Be careful this macro open a C scope that it expect to be closed by
 * EINA_COW_WRITE_END().
 */
#define EINA_COW_WRITE_BEGIN(Cow, Read, Write_Type, Write)		\
  do									\
    {									\
      Write_Type *Write;						\
      									\
      Write = eina_cow_write(Cow, ((const Eina_Cow_Data**)&(Read)));

/**
 * @def EINA_COW_WRITE_END
 * @brief This macro close the writable pointer.
 * @param Cow The Eina_Cow where the const pointer come from.
 * @param Read The const pointer to get a writable handler from.
 * @param Write The name of the variable where to put the writeable pointer to.
 * @since 1.8.0
 *
 * Be careful this macro close the scope opened by EINA_COW_WRITE_BEGIN().
 */
#define EINA_COW_WRITE_END(Cow, Read, Write)				\
      eina_cow_done(Cow, ((const Eina_Cow_Data**)&(Read)), Write,	\
		    EINA_TRUE);						\
    }									\
  while (0);

/**
 * @}
 */

/**
 * @}
 */

#endif