Skip to content

Commit

Permalink
Context cleanup (Azure#1158)
Browse files Browse the repository at this point in the history
* Context cleanup
  • Loading branch information
RickWinter authored Aug 29, 2020
1 parent 1ab7de1 commit 02b545e
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 42 deletions.
57 changes: 15 additions & 42 deletions sdk/inc/azure/core/az_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@

/**
* @brief A context is a node within a tree that represents expiration times and key/value pairs.
*
* @details The root node in the tree (ultimate parent) is #az_context_application which is a
* context for the entire application. Each new node is a child of some parent.
*/
// Definition is below. Defining the typedef first is necessary here since there is a cycle.
typedef struct az_context az_context;

/**
* @brief A context is a node within a tree that represents expiration times and key/value pairs.
*
* @details The root node in the tree (ultimate parent) is #az_context_application which is a
* context for the entire application. Each new node is a child of some parent.
* @details The root node in the tree (ultimate parent).
*/
struct az_context
{
Expand All @@ -51,60 +47,41 @@ struct az_context
#define _az_CONTEXT_MAX_EXPIRATION 0x7FFFFFFFFFFFFFFF

/**
* @brief The ultimate root of all #az_context instances. It allows you to cancel your entire
* application. The #az_context_application never expires but you can explicitly cancel it by
* passing its address to #az_context_cancel which effectively cancels all the #az_context child
* nodes.
* @brief The application root #az_context instances.
* @details The #az_context_application never expires but you can explicitly cancel it by passing its address to
* #az_context_cancel() which effectively cancels all its #az_context child nodes.
*/
extern az_context az_context_application;

/**
* @brief Creates a new expiring #az_context node that is a child of the specified parent.
*
* @param[in] parent The #az_context node that the new node is to be a child of; passing `NULL` sets
* the parent to #az_context_application.
* @param[in] expiration The time when this new child node should be canceled.
* @param[in] parent The #az_context node that is the parent to the new node.
* @param[in] expiration The time when this new node should be canceled.
*
* @return The new child #az_context node.
*/
AZ_NODISCARD AZ_INLINE az_context
az_context_create_with_expiration(az_context const* parent, int64_t expiration)
{
return (az_context){ ._internal
= { .parent = ((parent != NULL) ? parent : &az_context_application),
.expiration = expiration } };
}
AZ_NODISCARD az_context
az_context_create_with_expiration(az_context const* parent, int64_t expiration);

/**
* @brief Creates a new key/value az_context node that is a child of the specified parent.
*
* @param[in] parent __[nullable]__ The #az_context node that the new node is to be a child of;
* passing `NULL` sets the parent to #az_context_application.
* @param[in] parent The #az_context node that is the parent to the new node.
* @param[in] key A pointer to the key of this new #az_context node.
* @param[in] value A pointer to the value of this new #az_context node.
*
* @return The new child #az_context node.
*/
AZ_NODISCARD AZ_INLINE az_context
az_context_create_with_value(az_context const* parent, void const* key, void const* value)
{
return (az_context){ ._internal = { .parent = (parent != NULL) ? parent : &az_context_application,
.expiration = _az_CONTEXT_MAX_EXPIRATION,
.key = key,
.value = value } };
}
AZ_NODISCARD az_context
az_context_create_with_value(az_context const* parent, void const* key, void const* value);

/**
* @brief Cancels the specified #az_context node; this cancels all the child nodes as well.
*
* @param[in,out] ref_context __[nullable]__ A pointer to the #az_context node to be canceled;
* passing `NULL` cancels the #az_context_application.
* @param[in,out] ref_context A pointer to the #az_context node to be canceled.
*/
AZ_INLINE void az_context_cancel(az_context* ref_context)
{
ref_context = ((ref_context != NULL) ? ref_context : &az_context_application);
ref_context->_internal.expiration = 0; // The beginning of time
}
void az_context_cancel(az_context* ref_context);

/**
* @brief Returns the soonest expiration time of this #az_context node or any of its parent nodes.
Expand All @@ -118,14 +95,10 @@ AZ_NODISCARD int64_t az_context_get_expiration(az_context const* context);
* @brief Returns `true` if this #az_context node or any of its parent nodes' expiration is before
* the \p current_time.
*
* @param[in] context A pointer to the #az_context node to check; passing `NULL` checks the root
* #az_context_application.
* @param[in] context A pointer to the #az_context node to check.
* @param[in] current_time The current time.
*/
AZ_NODISCARD AZ_INLINE bool az_context_has_expired(az_context const* context, int64_t current_time)
{
return az_context_get_expiration(context) < current_time;
}
AZ_NODISCARD bool az_context_has_expired(az_context const* context, int64_t current_time);

/**
* @brief Walks up this #az_context node's parents until it find a node whose key matches the
Expand Down
43 changes: 43 additions & 0 deletions sdk/src/azure/core/az_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: MIT

#include <azure/core/az_context.h>
#include <azure/core/internal/az_precondition_internal.h>

#include <stddef.h>

Expand All @@ -18,6 +19,8 @@ az_context az_context_application = {
// Returns the soonest expiration time of this az_context node or any of its parent nodes.
AZ_NODISCARD int64_t az_context_get_expiration(az_context const* context)
{
_az_PRECONDITION_NOT_NULL(context);

int64_t expiration = _az_CONTEXT_MAX_EXPIRATION;
for (; context != NULL; context = context->_internal.parent)
{
Expand All @@ -33,6 +36,10 @@ AZ_NODISCARD int64_t az_context_get_expiration(az_context const* context)
AZ_NODISCARD az_result
az_context_get_value(az_context const* context, void const* key, void const** out_value)
{
_az_PRECONDITION_NOT_NULL(context);
_az_PRECONDITION_NOT_NULL(out_value);
_az_PRECONDITION_NOT_NULL(key);

for (; context != NULL; context = context->_internal.parent)
{
if (context->_internal.key == key)
Expand All @@ -44,3 +51,39 @@ az_context_get_value(az_context const* context, void const* key, void const** ou
*out_value = NULL;
return AZ_ERROR_ITEM_NOT_FOUND;
}

AZ_NODISCARD az_context
az_context_create_with_expiration(az_context const* parent, int64_t expiration)
{
_az_PRECONDITION_NOT_NULL(parent);
_az_PRECONDITION(expiration >= 0);

return (az_context){ ._internal = { .parent = parent, .expiration = expiration } };
}

AZ_NODISCARD az_context
az_context_create_with_value(az_context const* parent, void const* key, void const* value)
{
_az_PRECONDITION_NOT_NULL(parent);
_az_PRECONDITION_NOT_NULL(key);

return (az_context){
._internal
= { .parent = parent, .expiration = _az_CONTEXT_MAX_EXPIRATION, .key = key, .value = value }
};
}

void az_context_cancel(az_context* ref_context)
{
_az_PRECONDITION_NOT_NULL(ref_context);

ref_context->_internal.expiration = 0; // The beginning of time
}

AZ_NODISCARD bool az_context_has_expired(az_context const* context, int64_t current_time)
{
_az_PRECONDITION_NOT_NULL(context);
_az_PRECONDITION(current_time >= 0);

return az_context_get_expiration(context) < current_time;
}

0 comments on commit 02b545e

Please sign in to comment.