/
triRefcount.c
128 lines (109 loc) · 2.7 KB
/
triRefcount.c
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
/*
* triRefcount.c: Code for refcounting ressources
* This file is part of the "tri Engine".
*
* Copyright (C) 2007 tri
* Copyright (C) 2007 Alexander Berl 'Raphael' <raphael@fx-world.org>
*
* $Id: $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include "triRefcount.h"
#include "triMemory.h"
typedef struct triRefcount
{
triChar* id;
triVoid* data;
triS32 refs;
struct triRefcount* next;
} triRefcount;
static triRefcount* triRefcountList = 0;
triVoid triRefcountCreate( const triChar* id, triVoid* data )
{
if (id==0 || data==0) return;
triRefcount* r = triMalloc(sizeof(triRefcount));
if (r==0) return;
r->id = triMalloc(strlen(id)+1);
strcpy(r->id, id);
r->id[strlen(id)] = 0;
r->data = data;
r->refs = 1;
r->next = triRefcountList;
triRefcountList = r;
}
// returns pointer to data if already in refcount list
// else NULL (create a new refcount for that id)
triVoid* triRefcountRetain( const triChar* id )
{
if (id==0) return(0);
triRefcount* r = triRefcountList;
while (r!=0)
{
if (stricmp(id, r->id)==0)
{
r->refs++;
return(r->data);
}
r = r->next;
}
return(0);
}
// returns pointer to data if already in refcount list
// else NULL (create a new refcount for that ptr)
triVoid* triRefcountRetainPtr( const triVoid* ptr )
{
if (ptr==0) return(0);
triRefcount* r = triRefcountList;
while (r!=0)
{
if (ptr == r->data)
{
r->refs++;
return(r->data);
}
r = r->next;
}
return(0);
}
// returns 0 if the resource can be freed savely
triS32 triRefcountRelease( const triVoid* data )
{
if (data==0) return -1;
triRefcount* r = triRefcountList;
triRefcount* l = 0;
while (r!=0)
{
if (data == r->data)
{
r->refs--;
if (r->refs==0)
{
if (l==0)
triRefcountList = r->next;
else
l->next = r->next;
triFree(r->id);
triFree(r);
return(0);
}
return(r->refs);
}
l = r;
r = r->next;
}
return(0);
}