Преглед на файлове

Add (and use) generic reference counter, to improve signal:noise ratio

in code defining reference-counted objects.
tags/v0.9.3
Michael Brown преди 17 години
родител
ревизия
d40761d725
променени са 8 файла, в които са добавени 128 реда и са изтрити 58 реда
  1. 3
    40
      src/core/interface.c
  2. 1
    1
      src/core/job.c
  3. 73
    0
      src/core/refcnt.c
  4. 1
    1
      src/core/xfer.c
  5. 6
    9
      src/include/gpxe/interface.h
  6. 3
    4
      src/include/gpxe/job.h
  7. 39
    0
      src/include/gpxe/refcnt.h
  8. 2
    3
      src/include/gpxe/xfer.h

+ 3
- 40
src/core/interface.c Целия файл

@@ -16,7 +16,6 @@
16 16
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 17
  */
18 18
 
19
-#include <assert.h>
20 19
 #include <gpxe/interface.h>
21 20
 
22 21
 /** @file
@@ -25,30 +24,6 @@
25 24
  *
26 25
  */
27 26
 
28
-/**
29
- * Obtain reference to interface
30
- *
31
- * @v intf		Interface
32
- * @ret intf		Interface
33
- *
34
- * Increases the reference count on the interface.
35
- */
36
-static struct interface * intf_get ( struct interface *intf ) {
37
-	intf->refcnt ( intf, +1 );
38
-	return intf;
39
-}
40
-
41
-/**
42
- * Drop reference to interface
43
- *
44
- * @v intf		Interface
45
- *
46
- * Decreases the reference count on the interface.
47
- */
48
-static void intf_put ( struct interface *intf ) {
49
-	intf->refcnt ( intf, -1 );
50
-}
51
-
52 27
 /**
53 28
  * Plug an interface into a new destination interface
54 29
  *
@@ -63,19 +38,7 @@ static void intf_put ( struct interface *intf ) {
63 38
  * interface into a null interface.
64 39
  */
65 40
 void plug ( struct interface *intf, struct interface *dest ) {
66
-	intf_put ( intf->dest );
67
-	intf->dest = intf_get ( dest );
68
-}
69
-
70
-/**
71
- * Null update reference count
72
- *
73
- * @v intf		Interface
74
- * @v delta		Change to apply to reference count
75
- *
76
- * Use this as the refcnt() method for an interface that does not need
77
- * to support reference counting.
78
- */
79
-void null_refcnt ( struct interface *intf __unused, int delta __unused ) {
80
-	/* Do nothing */
41
+	ref_put ( intf->refcnt );
42
+	ref_get ( dest->refcnt );
43
+	intf->dest = dest;
81 44
 }

+ 1
- 1
src/core/job.c Целия файл

@@ -71,7 +71,7 @@ struct job_interface_operations null_job_ops = {
71 71
 struct job_interface null_job = {
72 72
 	.intf = {
73 73
 		.dest = &null_job.intf,
74
-		.refcnt = null_refcnt,
74
+		.refcnt = NULL,
75 75
 	},
76 76
 	.op = &null_job_ops,
77 77
 };

+ 73
- 0
src/core/refcnt.c Целия файл

@@ -0,0 +1,73 @@
1
+/*
2
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <stdlib.h>
20
+#include <gpxe/refcnt.h>
21
+
22
+/** @file
23
+ *
24
+ * Reference counting
25
+ *
26
+ */
27
+
28
+/**
29
+ * Increment reference count
30
+ *
31
+ * @v refcnt		Reference counter, or NULL
32
+ *
33
+ * If @c refcnt is NULL, no action is taken.
34
+ */
35
+void ref_get ( struct refcnt *refcnt ) {
36
+
37
+	if ( ! refcnt )
38
+		return;
39
+
40
+	refcnt->refcnt++;
41
+
42
+	DBGC ( refcnt, "REFCNT %p incremented to %d\n",
43
+	       refcnt, refcnt->refcnt );
44
+}
45
+
46
+/**
47
+ * Decrement reference count
48
+ *
49
+ * @v refcnt		Reference counter, or NULL
50
+ *
51
+ * If the reference count decreases below zero, the object's free()
52
+ * method will be called.
53
+ *
54
+ * If @c refcnt is NULL, no action is taken.
55
+ */
56
+void ref_put ( struct refcnt *refcnt ) {
57
+
58
+	if ( ! refcnt )
59
+		return;
60
+
61
+	refcnt->refcnt--;
62
+	DBGC ( refcnt, "REFCNT %p decremented to %d\n",
63
+	       refcnt, refcnt->refcnt );
64
+
65
+	if ( refcnt->refcnt >= 0 )
66
+		return;
67
+
68
+	if ( refcnt->free ) {
69
+		refcnt->free ( refcnt );
70
+	} else {
71
+		free ( refcnt );
72
+	}
73
+}

+ 1
- 1
src/core/xfer.c Целия файл

@@ -230,7 +230,7 @@ struct xfer_interface_operations null_xfer_ops = {
230 230
 struct xfer_interface null_xfer = {
231 231
 	.intf = {
232 232
 		.dest = &null_xfer.intf,
233
-		.refcnt = null_refcnt,
233
+		.refcnt = NULL,
234 234
 	},
235 235
 	.op = &null_xfer_ops,
236 236
 };

+ 6
- 9
src/include/gpxe/interface.h Целия файл

@@ -7,6 +7,8 @@
7 7
  *
8 8
  */
9 9
 
10
+#include <gpxe/refcnt.h>
11
+
10 12
 /** An object communication interface */
11 13
 struct interface {
12 14
 	/** Destination interface
@@ -18,19 +20,14 @@ struct interface {
18 20
 	 * unplugged, it should point to a null interface.
19 21
 	 */
20 22
 	struct interface *dest;
21
-	/** Update reference count
22
-	 *
23
-	 * @v intf		Interface
24
-	 * @v delta		Change to apply to reference count
23
+	/** Reference counter
25 24
 	 *
26
-	 * This method updates the reference count for the object
27
-	 * containing the interface.
25
+	 * If this interface is not part of a reference-counted
26
+	 * object, this field may be NULL.
28 27
 	 */
29
-	void ( * refcnt ) ( struct interface *intf, int delta );
28
+	struct refcnt *refcnt;
30 29
 };
31 30
 
32 31
 extern void plug ( struct interface *intf, struct interface *dest );
33 32
 
34
-extern void null_refcnt ( struct interface *intf, int delta );
35
-
36 33
 #endif /* _GPXE_INTERFACE_H */

+ 3
- 4
src/include/gpxe/job.h Целия файл

@@ -76,12 +76,11 @@ extern void ignore_progress ( struct job_interface *job,
76 76
  *
77 77
  * @v job		Job control interface
78 78
  * @v op		Job control interface operations
79
- * @v refcnt		Job control interface reference counting method
79
+ * @v refcnt		Containing object reference counter, or NULL
80 80
  */
81 81
 static inline void job_init ( struct job_interface *job,
82
-			       struct job_interface_operations *op,
83
-			       void ( * refcnt ) ( struct interface *intf,
84
-						   int delta ) ) {
82
+			      struct job_interface_operations *op,
83
+			      struct refcnt *refcnt ) {
85 84
 	job->intf.dest = &null_job.intf;
86 85
 	job->intf.refcnt = refcnt;
87 86
 	job->op = op;

+ 39
- 0
src/include/gpxe/refcnt.h Целия файл

@@ -0,0 +1,39 @@
1
+#ifndef _GPXE_REFCNT_H
2
+#define _GPXE_REFCNT_H
3
+
4
+/** @file
5
+ *
6
+ * Reference counting
7
+ *
8
+ */
9
+
10
+/**
11
+ * A reference counter
12
+ *
13
+ * This data structure is designed to be embedded within a
14
+ * reference-counted object.
15
+ */
16
+struct refcnt {
17
+	/** Current reference count
18
+	 *
19
+	 * When this count is decremented below zero, the free()
20
+	 * method will be called.
21
+	 */
22
+	int refcnt;
23
+	/** Free containing object
24
+	 *
25
+	 * This method is called when the reference count is
26
+	 * decremented below zero.
27
+	 *
28
+	 * If this method is left NULL, the standard library free()
29
+	 * function will be called.  The upshot of this is that you
30
+	 * may omit the free() method if the @c refcnt object is the
31
+	 * first element of your reference-counted struct.
32
+	 */
33
+	void ( * free ) ( struct refcnt *refcnt );
34
+};
35
+
36
+extern void ref_get ( struct refcnt *refcnt );
37
+extern void ref_put ( struct refcnt *refcnt );
38
+
39
+#endif /* _GPXE_REFCNT_H */

+ 2
- 3
src/include/gpxe/xfer.h Целия файл

@@ -114,12 +114,11 @@ extern int ignore_deliver_raw ( struct xfer_interface *xfer,
114 114
  *
115 115
  * @v xfer		Data transfer interface
116 116
  * @v op		Data transfer interface operations
117
- * @v refcnt		Data transfer interface reference counting method
117
+ * @v refcnt		Containing object reference counter, or NULL
118 118
  */
119 119
 static inline void xfer_init ( struct xfer_interface *xfer,
120 120
 			       struct xfer_interface_operations *op,
121
-			       void ( * refcnt ) ( struct interface *intf,
122
-						   int delta ) ) {
121
+			       struct refcnt *refcnt ) {
123 122
 	xfer->intf.dest = &null_xfer.intf;
124 123
 	xfer->intf.refcnt = refcnt;
125 124
 	xfer->op = op;

Loading…
Отказ
Запис