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

#ifndef INCLUDED_GRAS_SBUFFER_HPP
#define INCLUDED_GRAS_SBUFFER_HPP

#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);

    //! 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);

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

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

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

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

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

    //! 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/sbuffer.ipp>

#endif /*INCLUDED_GRAS_SBUFFER_HPP*/