File: deferred.h

package info (click to toggle)
amqp-cpp 4.3.27-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,384 kB
  • sloc: cpp: 10,021; ansic: 191; makefile: 95
file content (311 lines) | stat: -rw-r--r-- 8,107 bytes parent folder | download
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
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
/**
 *  Deferred.h
 *
 *  Class describing a set of actions that could
 *  possibly happen in the future that can be
 *  caught.
 *
 *  @copyright 2014 - 2020 Copernica BV
 */

/**
 *  Include guard
 */
#pragma once

/**
 *  Dependencies
 */
#include <memory>
#include <stdint.h>
#include "callbacks.h"

/**
 *  Set up namespace
 */
namespace AMQP {

// forward declaration
class ChannelImpl;

/**
 *  Class definition
 */
class Deferred
{
private:
    /**
     *  Callback to execute either way
     *  @var    FinalizeCallback
     */
    FinalizeCallback _finalizeCallback;

protected:
    /**
     *  Callback to execute on success
     *  @var    SuccessCallback
     */
    SuccessCallback _successCallback;

    /**
     *  Callback to execute on failure
     *  @var    ErrorCallback
     */
    ErrorCallback _errorCallback;

    /**
     *  Pointer to the next deferred object
     *  @var    Deferred
     */
    std::shared_ptr<Deferred> _next;

    /**
     *  Do we already know we failed?
     *  @var bool
     */
    bool _failed;


    /**
     *  The next deferred object
     *  @return Deferred
     */
    const std::shared_ptr<Deferred> &next() const
    {
        return _next;
    }

    /**
     *  Indicate success
     *  @return Deferred        Next deferred result
     */
    virtual const std::shared_ptr<Deferred> &reportSuccess() const
    {
        // execute callbacks if registered
        if (_successCallback) _successCallback();

        // return the next deferred result
        return _next;
    }

    /**
     *  Report success for queue declared messages
     *  @param  name            Name of the new queue
     *  @param  messagecount    Number of messages in the queue
     *  @param  consumercount   Number of consumers linked to the queue
     *  @return Deferred        Next deferred result
     */
    virtual const std::shared_ptr<Deferred> &reportSuccess(const std::string &name, uint32_t messagecount, uint32_t consumercount) const
    {
        // make sure compilers dont complain about unused parameters
        (void) name;
        (void) messagecount;
        (void) consumercount;

        // this is the same as a regular success message
        return reportSuccess();
    }

    /**
     *  Report success for frames that report delete operations
     *  @param  messagecount    Number of messages that were deleted
     *  @return Deferred
     */
    virtual const std::shared_ptr<Deferred> &reportSuccess(uint32_t messagecount) const
    {
        // make sure compilers dont complain about unused parameters
        (void) messagecount;

        // this is the same as a regular success message
        return reportSuccess();
    }

    /**
     *  Report success for a get operation
     *
     *  @param  messagecount    Number of messages left in the queue
     *  @param  deliveryTag     Delivery tag of the message coming in
     *  @param  redelivered     Was the message redelivered?
     */
    virtual const std::shared_ptr<Deferred> &reportSuccess(uint32_t messagecount, uint64_t deliveryTag, bool redelivered)
    {
        // make sure compilers dont complain about unused parameters
        (void) messagecount;
        (void) deliveryTag;
        (void) redelivered;

        // this is the same as a regular success message
        return reportSuccess();
    }

    /**
     *  Report success for frames that report cancel operations
     *  @param  name            Consumer tag that is cancelled
     *  @return Deferred
     */
    virtual const std::shared_ptr<Deferred> &reportSuccess(const std::string &name)
    {
        // make sure compilers dont complain about unused parameters
        (void) name;

        // this is the same as a regular success message
        return reportSuccess();
    }

    /**
     *  Indicate failure
     *  @param  error           Description of the error that occured
     *  @return Deferred        Next deferred result
     */
    const std::shared_ptr<Deferred> &reportError(const char *error)
    {
        // from this moment on the object should be listed as failed
        _failed = true;

        // execute callbacks if registered
        if (_errorCallback) _errorCallback(error);

        // return the next deferred result
        return _next;
    }

    /**
     *  Add a pointer to the next deferred result
     *  @param  deferred
     */
    void add(const std::shared_ptr<Deferred> &deferred)
    {
        // store pointer
        _next = deferred;
    }
    
    /**
     *  Remove this object from the chain of deferreds
     */
    void unchain()
    {
        // we no longer need the next pointer
        _next = nullptr;
    }

    /**
     *  The channel implementation may call our
     *  private members and construct us
     */
    friend class ChannelImpl;
    friend class Tagger;

public:
    /**
     *  Protected constructor that can only be called
     *  from within the channel implementation
     *
     *  Note: this constructor _should_ be protected, but because make_shared
     *  will then not work, we have decided to make it public after all,
     *  because the work-around would result in not-so-easy-to-read code.
     *
     *  @param  failed  are we already failed?
     */
    Deferred(bool failed = false) : _failed(failed) {}

public:
    /**
     *  Deleted copy and move constructors
     */
    Deferred(const Deferred &that) = delete;
    Deferred(Deferred &&that) = delete;

    /**
     *  Destructor
     */
    virtual ~Deferred()
    {
        // report to the finalize callback
        if (_finalizeCallback) _finalizeCallback();
    }

    /**
     *  Cast to a boolean
     */
    operator bool () const
    {
        return !_failed;
    }

    /**
     *  Register a function to be called
     *  if and when the operation succesfully
     *  completes.
     *
     *  Only one callback can be registered at a time.
     *  Successive calls to this function will clear
     *  callbacks registered before.
     *
     *  @param  callback    the callback to execute
     */
    inline Deferred &onSuccess(const SuccessCallback& callback) { return onSuccess(SuccessCallback(callback)); }
    Deferred &onSuccess(SuccessCallback&& callback)
    {
        // store callback
        _successCallback = std::move(callback);

        // allow chaining
        return *this;
    }

    /**
     *  Register a function to be called
     *  if and when the operation fails.
     *
     *  Only one callback can be registered at a time.
     *  Successive calls to this function will clear
     *  callbacks registered before.
     *
     *  @param  callback    the callback to execute
     */
    inline Deferred &onError(const ErrorCallback& callback) { return onError(ErrorCallback(callback)); }
    Deferred &onError(ErrorCallback&& callback)
    {
        // store callback
        _errorCallback = std::move(callback);

        // if the object is already in a failed state, we call the callback right away
        if (_failed) _errorCallback("Frame could not be sent");

        // allow chaining
        return *this;
    }

    /**
     *  Register a function to be called
     *  if and when the operation completes
     *  or fails. This function will be called
     *  either way.
     *
     *  In the case of success, the provided
     *  error parameter will be an empty string.
     *
     *  Only one callback can be registered at at time.
     *  Successive calls to this function will clear
     *  callbacks registered before.
     *
     *  @param  callback    the callback to execute
     */
    inline Deferred &onFinalize(const FinalizeCallback& callback) { return onFinalize(FinalizeCallback(callback)); }
    Deferred &onFinalize(FinalizeCallback&& callback)
    {
        // if the object is already in a failed state, we call the callback right away
        if (_failed) callback();

        // otherwise we store callback until it's time for the call
        else _finalizeCallback = std::move(callback);

        // allow chaining
        return *this;
    }
};

/**
 *  End namespace
 */
}