summaryrefslogtreecommitdiff
path: root/include/gras/sbuffer.hpp
blob: d1bc2d13e19f6932335f305ca40fc8fc05208f44 (plain)
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
// Copyright (C) by Josh Blum. See LICENSE.txt for licensing information.

#ifndef INCLUDED_GRAS_SBUFFER_HPP
#define INCLUDED_GRAS_SBUFFER_HPP

#ifdef _MSC_VER
#pragma warning(push)
#pragma warning (disable:4251)  // needs to have dll interface
#endif //_MSC_VER

#include <gras/gras.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>

namespace gras
{

struct SBufferImpl;
struct SBuffer;

//! The callback function type when buffers dereference
typedef boost::function<void(SBuffer &)> SBufferDeleter;

//! The token type held by the caller
typedef boost::shared_ptr<SBufferDeleter> SBufferToken;

//! The token type weak ptr help by buffer
typedef boost::weak_ptr<SBufferDeleter> SBufferTokenWeak;

struct GRAS_API SBufferConfig
{
    //! Default constructor zeros out buffer config
    SBufferConfig(void);

    //! Destructor
    ~SBufferConfig(void);

    //! pointer to the memory start
    void *memory;

    //! length of the memory in bytes
    size_t length;

    //! memory affinity - meta information
    long affinity;

    //! index number for custom allocation purposes
    size_t user_index;

    //! deleter callback, may be used to free
    SBufferDeleter deleter;

    //! token object, called if set under deref condition
    SBufferTokenWeak token;
};

/*!
 * SBuffer is a smart/shared reference counted handler of memory.
 * Thank you boost smart/shared pointers for the disambiguation!
 *
 * Default allocator:
 * To use the default system allocator, set the memory to NULL,
 * and set length and affinity to the desired values.
 * The deleter will be automaically configured by the allocator.
 *
 * Custom allocator:
 * Set all config struct members. Its all you!
 *
 * Token usage:
 * When a token is set, the buffer will not cleanup and call the deleter.
 * Rather, the bound function in the token will be called with the buffer.
 * A parent object should hold the shared pointer to the token.
 * When the parent object deconstructs, the weak pointer will die,
 * and the normal buffer cleanup/freeing/deconstruction will happen.
 *
 * Length and offset usage:
 * Length and offset are intentionally object members
 * and not part of the ref-counted intrusive_ptr guts.
 * These members should be modified carefully
 * to pass a subset of the memory downstream.
 *
 * Length and offset recommendation:
 * These values should probably be reset by the
 * bound token or when a fresh buffer is popped.
 */
struct GRAS_API SBuffer : boost::intrusive_ptr<SBufferImpl>
{
    //! Default constructor, zeros things
    SBuffer(void);

    /*!
     * Create a new buffer.
     * The config object represents a chunk of memory,
     * or instructions for the default allocator.
     */
    SBuffer(const SBufferConfig &config);

    //! Destructor
    ~SBuffer(void);

    /*!
     * Get a pointer to the start of the underlying memory
     */
    const void *get_actual_memory(void) const;

    /*!
     * Get a pointer to the start of the underlying memory
     */
    void *get_actual_memory(void);

    /*!
     * Get the length of the underlying memory in bytes
     */
    size_t get_actual_length(void) const;

    //! Get a pointer into valid memory
    const void *get(const ptrdiff_t delta_bytes = 0) const;

    //! Get a pointer into valid memory
    void *get(const ptrdiff_t delta_bytes = 0);

    //! The offset into valid memory in bytes
    size_t offset;

    //! The number of valid bytes past offset
    size_t length;

    //! Pointer to the end of the last buffer
    void *last;

    //! Get the affinity of the memory
    long get_affinity(void) const;

    //! Get the user index number
    size_t get_user_index(void) const;

    //! Unique if caller holds the only reference count
    bool unique(void) const;

    //! Get the number of reference holders
    size_t use_count(void) const;
};

} //namespace gras

#include <gras/detail/sbuffer.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif //_MSC_VER

#endif /*INCLUDED_GRAS_SBUFFER_HPP*/