Skip to content

Commit f5f1564

Browse files
committed
Update HPy inlined files: 2196f14
1 parent 7b9fc7e commit f5f1564

File tree

4 files changed

+465
-2
lines changed

4 files changed

+465
-2
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

22
// automatically generated by setup.py:get_scm_config()
33
#define HPY_VERSION "0.0.3"
4-
#define HPY_GIT_REVISION "33c8692"
4+
#define HPY_GIT_REVISION "2196f14"
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/**
2+
* A manager for HPy handles, allowing handles to be tracked
3+
* and closed as a group.
4+
*
5+
* Note::
6+
* Calling HPyTracker_New(ctx, n) will ensure that at least n handles
7+
* can be tracked without a call to HPyTracker_Add failing.
8+
*
9+
* If a call to HPyTracker_Add fails, the tracker still guarantees that
10+
* the handle passed to it has been tracked (internally it does this by
11+
* maintaining space for one more handle).
12+
*
13+
* After HPyTracker_Add fails, HPyTracker_Close should be called without
14+
* any further calls to HPyTracker_Add. Calling HPyTracker_Close will close
15+
* all the tracked handles, including the handled passed to the failed call
16+
* to HPyTracker_Add.
17+
*
18+
* Example usage (inside an HPyDef_METH function)::
19+
*
20+
* long i;
21+
* HPy key, value;
22+
* HPyTracker ht;
23+
*
24+
* ht = HPyTracker_New(ctx, 0); // track the key-value pairs
25+
* if (HPy_IsNull(ht))
26+
* return HPy_NULL;
27+
*
28+
* HPy dict = HPyDict_New(ctx);
29+
* if (HPy_IsNull(dict))
30+
* goto error;
31+
*
32+
* for (i=0; i<5; i++) {
33+
* key = HPyLong_FromLong(ctx, i);
34+
* if (HPy_IsNull(key))
35+
* goto error;
36+
* if (HPyTracker_Add(ctx, ht, key) < 0)
37+
* goto error;
38+
* value = HPyLong_FromLong(ctx, i * i);
39+
* if (HPy_IsNull(value)) {
40+
* goto error;
41+
* }
42+
* if (HPyTracker_Add(ctx, ht, value) < 0)
43+
* goto error;
44+
* result = HPy_SetItem(ctx, dict, key, value);
45+
* if (result < 0)
46+
* goto error;
47+
* }
48+
*
49+
* success:
50+
* HPyTracker_Close(ctx, ht);
51+
* return dict;
52+
*
53+
* error:
54+
* HPyTracker_Close(ctx, ht);
55+
* HPy_Close(ctx, dict);
56+
* // HPyErr will already have been set by the error that occurred.
57+
* return HPy_NULL;
58+
*/
59+
60+
#include "hpy.h"
61+
62+
static const HPy_ssize_t HPYTRACKER_INITIAL_CAPACITY = 5;
63+
64+
typedef struct {
65+
HPy_ssize_t capacity; // allocated handles
66+
HPy_ssize_t length; // used handles
67+
HPy *handles;
68+
} _HPyTracker_s;
69+
70+
71+
static inline _HPyTracker_s *_ht2hp(HPyTracker ht) {
72+
return (_HPyTracker_s *) (ht)._i;
73+
}
74+
static inline HPyTracker _hp2ht(_HPyTracker_s *hp) {
75+
return (HPyTracker) {(HPy_ssize_t) (hp)};
76+
}
77+
78+
79+
_HPy_HIDDEN HPyTracker
80+
ctx_Tracker_New(HPyContext *ctx, HPy_ssize_t capacity)
81+
{
82+
_HPyTracker_s *hp;
83+
if (capacity == 0) {
84+
capacity = HPYTRACKER_INITIAL_CAPACITY;
85+
}
86+
capacity++; // always reserve space for an extra handle, see the docs
87+
88+
hp = malloc(sizeof(_HPyTracker_s));
89+
if (hp == NULL) {
90+
HPyErr_NoMemory(ctx);
91+
return _hp2ht(0);
92+
}
93+
hp->handles = calloc(capacity, sizeof(HPy));
94+
if (hp->handles == NULL) {
95+
free(hp);
96+
HPyErr_NoMemory(ctx);
97+
return _hp2ht(0);
98+
}
99+
hp->capacity = capacity;
100+
hp->length = 0;
101+
// cppcheck thinks that hp->handles is a memory leak because we cast the
102+
// pointer to an int (and thus the pointer is "lost" from its POV, I
103+
// suppose). But it's not a real leak because we free it in
104+
// ctx_Tracker_Close:
105+
// cppcheck-suppress memleak
106+
return _hp2ht(hp);
107+
}
108+
109+
static int
110+
tracker_resize(HPyContext *ctx, _HPyTracker_s *hp, HPy_ssize_t capacity)
111+
{
112+
HPy *new_handles;
113+
capacity++;
114+
115+
if (capacity <= hp->length) {
116+
// refuse a resize that would either 1) lose handles or 2) not leave
117+
// space for one new handle
118+
HPyErr_SetString(ctx, ctx->h_ValueError, "HPyTracker resize would lose handles");
119+
return -1;
120+
}
121+
new_handles = realloc(hp->handles, capacity * sizeof(HPy));
122+
if (new_handles == NULL) {
123+
HPyErr_NoMemory(ctx);
124+
return -1;
125+
}
126+
hp->capacity = capacity;
127+
hp->handles = new_handles;
128+
return 0;
129+
}
130+
131+
_HPy_HIDDEN int
132+
ctx_Tracker_Add(HPyContext *ctx, HPyTracker ht, HPy h)
133+
{
134+
_HPyTracker_s *hp = _ht2hp(ht);
135+
hp->handles[hp->length++] = h;
136+
if (hp->capacity <= hp->length) {
137+
if (tracker_resize(ctx, hp, hp->capacity * 2 - 1) < 0)
138+
return -1;
139+
}
140+
return 0;
141+
}
142+
143+
_HPy_HIDDEN void
144+
ctx_Tracker_ForgetAll(HPyContext *ctx, HPyTracker ht)
145+
{
146+
_HPyTracker_s *hp = _ht2hp(ht);
147+
hp->length = 0;
148+
}
149+
150+
_HPy_HIDDEN void
151+
ctx_Tracker_Close(HPyContext *ctx, HPyTracker ht)
152+
{
153+
_HPyTracker_s *hp = _ht2hp(ht);
154+
HPy_ssize_t i;
155+
for (i=0; i<hp->length; i++) {
156+
HPy_Close(ctx, hp->handles[i]);
157+
}
158+
free(hp->handles);
159+
free(hp);
160+
}

0 commit comments

Comments
 (0)