Skip to content

Commit

Permalink
fixes #1751 Support nng_aio_set_expire().
Browse files Browse the repository at this point in the history
While here fixed a number of nits in comments.
  • Loading branch information
gdamore committed Dec 31, 2023
1 parent 9b26b72 commit 838c9ea
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 21 deletions.
11 changes: 10 additions & 1 deletion docs/man/nng_aio_set_timeout.3.adoc
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
= nng_aio_set_timeout(3)
//
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This document is supplied under the terms of the MIT License, a
Expand All @@ -21,6 +21,9 @@ nng_aio_set_timeout - set asynchronous I/O timeout
typedef int nng_duration;
void nng_aio_set_timeout(nng_aio *aio, nng_duration timeout);
typedef uint64_t nng_time;
void nng_aio_set_expire(nng_aio *aio, nng_time expiration);
----

== DESCRIPTION
Expand All @@ -37,6 +40,12 @@ If the timeout is `NNG_DURATION_DEFAULT`, then a "default" or socket-specific
timeout is used.
(This is frequently the same as `NNG_DURATION_INFINITE`.)

The `nng_aio_set_expire()` function is similar to `nng_aio_set_timeout()`, but sets
an absolute expiration time based on the system clock. The _expiration_
is expressed as a number of milliseconds since some point in the past.
The xref:nng_clock.3supp.adoc[`nng_clock()`] function can be used to determine
the current value of the clock.

TIP: As most operations involve some context switching, it is usually a good
idea to allow at least a few tens of milliseconds before timing them out --
a too small timeout might not allow the operation to properly begin before
Expand Down
2 changes: 1 addition & 1 deletion docs/man/nng_clock.3supp.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ arbitrary time in the past.
The resolution of the clock depends on the underlying timing facilities
of the system.
This function may be used for timing, but applications should not expect
very fine grained values.
very fine-grained values.

IMPORTANT: The reference time will be the same for a given program,
but different programs may have different references.
Expand Down
32 changes: 20 additions & 12 deletions include/nng/nng.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ typedef struct nng_socket_s {
} nng_socket;

typedef int32_t nng_duration; // in milliseconds

// nng_time represents an absolute time since some arbitrary point in the
// past, measured in milliseconds. The values are always positive.
typedef uint64_t nng_time;

typedef struct nng_msg nng_msg;
typedef struct nng_stat nng_stat;
typedef struct nng_aio nng_aio;
Expand Down Expand Up @@ -154,7 +159,7 @@ struct nng_sockaddr_abstract {
uint8_t sa_name[107]; // 108 linux/windows, without leading NUL
};

// nng_sockaddr_storage is the the size required to store any nng_sockaddr.
// nng_sockaddr_storage is the size required to store any nng_sockaddr.
// This size must not change, and no individual nng_sockaddr type may grow
// larger than this without breaking binary compatibility.
struct nng_sockaddr_storage {
Expand Down Expand Up @@ -354,7 +359,7 @@ NNG_DECL int nng_listener_get_ptr(nng_listener, const char *, void **);
NNG_DECL int nng_listener_get_ms(nng_listener, const char *, nng_duration *);
NNG_DECL int nng_listener_get_addr(nng_listener, const char *, nng_sockaddr *);

// nng_strerror returns a human readable string associated with the error
// nng_strerror returns a human-readable string associated with the error
// code supplied.
NNG_DECL const char *nng_strerror(int);

Expand All @@ -380,7 +385,7 @@ NNG_DECL int nng_recv(nng_socket, void *, size_t *, int);
// nng_sendmsg is like nng_send, but offers up a message structure, which
// gives the ability to provide more control over the message, including
// providing backtrace information. It also can take a message that was
// obtain via nn_recvmsg, allowing for zero copy forwarding.
// obtained via nn_recvmsg, allowing for zero copy forwarding.
NNG_DECL int nng_sendmsg(nng_socket, nng_msg *, int);

// nng_recvmsg is like nng_recv, but is used to obtain a message structure
Expand All @@ -393,7 +398,7 @@ NNG_DECL int nng_recvmsg(nng_socket, nng_msg **, int);
// the completion may be executed before the data has actually been delivered,
// but only when it is accepted for delivery. The supplied AIO must have
// been initialized, and have an associated message. The message will be
// "owned" by the socket if the operation completes successfully. Otherwise
// "owned" by the socket if the operation completes successfully. Otherwise,
// the caller is responsible for freeing it.
NNG_DECL void nng_send_aio(nng_socket, nng_aio *);

Expand Down Expand Up @@ -429,7 +434,7 @@ NNG_DECL int nng_ctx_id(nng_ctx);
// uses a local context instead of the socket global context.
NNG_DECL void nng_ctx_recv(nng_ctx, nng_aio *);

// nng_ctx_recvmsg is allows for receiving a message synchronously using
// nng_ctx_recvmsg allows for receiving a message synchronously using
// a context. It has the same semantics as nng_recvmsg, but operates
// on a context instead of a socket.
NNG_DECL int nng_ctx_recvmsg(nng_ctx, nng_msg **, int);
Expand Down Expand Up @@ -515,7 +520,7 @@ NNG_DECL void nng_aio_reap(nng_aio *);

// nng_aio_stop stops any outstanding operation, and waits for the
// AIO to be free, including for the callback to have completed
// execution. Therefore the caller must NOT hold any locks that
// execution. Therefore, the caller must NOT hold any locks that
// are acquired in the callback, or deadlock will occur.
NNG_DECL void nng_aio_stop(nng_aio *);

Expand Down Expand Up @@ -578,6 +583,11 @@ NNG_DECL void *nng_aio_get_output(nng_aio *, unsigned);
// that any socket specific timeout should be used.
NNG_DECL void nng_aio_set_timeout(nng_aio *, nng_duration);

// nng_aio_set_expire is like nng_aio_set_timeout, except it sets an absolute
// expiration time. This is useful when chaining actions on a single aio
// as part of a state machine.
NNG_DECL void nng_aio_set_expire(nng_aio *, nng_time);

// nng_aio_set_iov sets a scatter/gather vector on the aio. The iov array
// itself is copied. Data members (the memory regions referenced) *may* be
// copied as well, depending on the operation. This operation is guaranteed
Expand Down Expand Up @@ -943,7 +953,7 @@ NNG_DECL nng_stat *nng_stat_next(nng_stat *);
NNG_DECL nng_stat *nng_stat_child(nng_stat *);

// nng_stat_name is used to determine the name of the statistic.
// This is a human readable name. Statistic names, as well as the presence
// This is a human-readable name. Statistic names, as well as the presence
// or absence or semantic of any particular statistic are not part of any
// stable API, and may be changed without notice in future updates.
NNG_DECL const char *nng_stat_name(nng_stat *);
Expand Down Expand Up @@ -990,22 +1000,20 @@ enum nng_unit_enum {
NNG_UNIT_EVENTS = 4 // Some other type of event
};

// nng_stat_value returns returns the actual value of the statistic.
// nng_stat_value returns the actual value of the statistic.
// Statistic values reflect their value at the time that the corresponding
// snapshot was updated, and are undefined until an update is performed.
NNG_DECL uint64_t nng_stat_value(nng_stat *);

// nng_stat_value returns returns the actual value of the statistic.
// Statistic values reflect their value at the time that the corresponding
// snapshot was updated, and are undefined until an update is performed.
// nng_stat_bool returns the boolean value of the statistic.
NNG_DECL bool nng_stat_bool(nng_stat *);

// nng_stat_string returns the string associated with a string statistic,
// or NULL if the statistic is not part of the string. The value returned
// is valid until the associated statistic is freed.
NNG_DECL const char *nng_stat_string(nng_stat *);

// nng_stat_desc returns a human readable description of the statistic.
// nng_stat_desc returns a human-readable description of the statistic.
// This may be useful for display in diagnostic interfaces, etc.
NNG_DECL const char *nng_stat_desc(nng_stat *);

Expand Down
8 changes: 2 additions & 6 deletions include/nng/supplemental/util/platform.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -27,13 +27,9 @@
extern "C" {
#endif

// nng_time represents an absolute time since some arbitrary point in the
// past, measured in milliseconds. The values are always positive.
typedef uint64_t nng_time;

// Return an absolute time from some arbitrary point. The value is
// provided in milliseconds, and is of limited resolution based on the
// system clock. (Do not use it for fine grained performance measurements.)
// system clock. (Do not use it for fine-grained performance measurements.)
NNG_DECL nng_time nng_clock(void);

// Sleep for specified msecs.
Expand Down
24 changes: 23 additions & 1 deletion src/core/aio_test.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// Copyright 2022 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2023 Staysail Systems, Inc. <info@staysail.tech>
// Copyright 2018 Capitar IT Group BV <info@capitar.com>
//
// This software is supplied under the terms of the MIT License, a
Expand Down Expand Up @@ -190,6 +190,27 @@ test_explicit_timeout(void)
NUTS_PASS(nng_close(s));
}

void
test_explicit_expiration(void)
{
nng_socket s;
nng_aio * a;
int done = 0;
nng_time now;

NUTS_PASS(nng_pair1_open(&s));
NUTS_PASS(nng_aio_alloc(&a, cb_done, &done));
now = nng_clock();
now += 40;
nng_aio_set_expire(a, now);
nng_recv_aio(s, a);
nng_aio_wait(a);
NUTS_TRUE(done == 1);
NUTS_FAIL(nng_aio_result(a), NNG_ETIMEDOUT);
nng_aio_free(a);
NUTS_PASS(nng_close(s));
}

void
test_inherited_timeout(void)
{
Expand Down Expand Up @@ -384,6 +405,7 @@ NUTS_TESTS = {
{ "consumer cancel", test_consumer_cancel },
{ "traffic", test_traffic },
{ "explicit timeout", test_explicit_timeout },
{ "explicit expire", test_explicit_expiration },
{ "inherited timeout", test_inherited_timeout },
{ "zero timeout", test_zero_timeout },
{ "aio reap", test_aio_reap },
Expand Down
6 changes: 6 additions & 0 deletions src/nng.c
Original file line number Diff line number Diff line change
Expand Up @@ -1919,6 +1919,12 @@ nng_aio_set_timeout(nng_aio *aio, nni_duration when)
nni_aio_set_timeout(aio, when);
}

void
nng_aio_set_expire(nng_aio *aio, nng_time when)
{
nni_aio_set_expire(aio, when);
}

int
nng_aio_set_iov(nng_aio *aio, unsigned niov, const nng_iov *iov)
{
Expand Down

0 comments on commit 838c9ea

Please sign in to comment.