Skip to content

Commit fbc1c12

Browse files
committed
Add a crude facility for dealing with relative pointers.
C doesn't have any sort of built-in understanding of a pointer relative to some arbitrary base address, but dynamic shared memory segments can be mapped at different addresses in different processes, so any sort of shared data structure stored within a dynamic shared memory segment can't use absolute pointers. We could use something like Size to represent a relative pointer, but then the compiler provides no type-checking. Use stupid macro tricks to get some type-checking. Patch originally by me. Concept suggested by Andres Freund. Recently resubmitted as part of Thomas Munro's work on dynamic shared memory allocation. Discussion: 20131205144434.GG12398@alap2.anarazel.de Discussion: CAEepm=1z5WLuNoJ80PaCvz6EtG9dN0j-KuHcHtU6QEfcPP5-qA@mail.gmail.com
1 parent e63d414 commit fbc1c12

File tree

1 file changed

+74
-0
lines changed

1 file changed

+74
-0
lines changed

src/include/utils/relptr.h

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* relptr.h
4+
* This file contains basic declarations for relative pointers.
5+
*
6+
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/include/utils/relptr.h
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#ifndef RELPTR_H
15+
#define RELPTR_H
16+
17+
/*
18+
* Relative pointers are intended to be used when storing an address that may
19+
* be relative either to the base of the processes address space or some
20+
* dynamic shared memory segment mapped therein.
21+
*
22+
* The idea here is that you declare a relative pointer as relptr(type)
23+
* and then use relptr_access to dereference it and relptr_store to change
24+
* it. The use of a union here is a hack, because what's stored in the
25+
* relptr is always a Size, never an actual pointer. But including a pointer
26+
* in the union allows us to use stupid macro tricks to provide some measure
27+
* of type-safety.
28+
*/
29+
#define relptr(type) union { type *relptr_type; Size relptr_off; }
30+
31+
/*
32+
* pgindent gets confused by declarations of the type relptr(type), so it's
33+
* useful to give them a name that doesn't include parentheses.
34+
*/
35+
#define relptr_declare(type, name) \
36+
typedef union { type *relptr_type; Size relptr_off; } name;
37+
38+
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
39+
#define relptr_access(base, rp) \
40+
(AssertVariableIsOfTypeMacro(base, char *), \
41+
(__typeof__((rp).relptr_type)) ((rp).relptr_off == 0 ? NULL : \
42+
(base + (rp).relptr_off)))
43+
#else
44+
/*
45+
* If we don't have __builtin_types_compatible_p, assume we might not have
46+
* __typeof__ either.
47+
*/
48+
#define relptr_access(base, rp) \
49+
(AssertVariableIsOfTypeMacro(base, char *), \
50+
(void *) ((rp).relptr_off == 0 ? NULL : (base + (rp).relptr_off)))
51+
#endif
52+
53+
#define relptr_is_null(rp) \
54+
((rp).relptr_off == 0)
55+
56+
#ifdef HAVE__BUILTIN_TYPES_COMPATIBLE_P
57+
#define relptr_store(base, rp, val) \
58+
(AssertVariableIsOfTypeMacro(base, char *), \
59+
AssertVariableIsOfTypeMacro(val, __typeof__((rp).relptr_type)), \
60+
(rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
61+
#else
62+
/*
63+
* If we don't have __builtin_types_compatible_p, assume we might not have
64+
* __typeof__ either.
65+
*/
66+
#define relptr_store(base, rp, val) \
67+
(AssertVariableIsOfTypeMacro(base, char *), \
68+
(rp).relptr_off = ((val) == NULL ? 0 : ((char *) (val)) - (base)))
69+
#endif
70+
71+
#define relptr_copy(rp1, rp2) \
72+
((rp1).relptr_off = (rp2).relptr_off)
73+
74+
#endif /* RELPTR_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy