mirror of https://github.com/grpc/grpc.git
commit
63cae4f11a
202 changed files with 7756 additions and 3015 deletions
@ -0,0 +1,30 @@ |
||||
# HTTP to gRPC Status Code Mapping |
||||
|
||||
Since intermediaries are a common part of HTTP infrastructure some responses to |
||||
gRPC requests may be received that do not include the grpc-status header. In |
||||
some cases mapping error codes from an intermediary allows the gRPC client to |
||||
behave more appropriately to the error situation without overloading the |
||||
semantics of either error code. |
||||
|
||||
This table is to be used _only_ for clients that received a response that did |
||||
not include grpc-status. If grpc-status was provided, it _must_ be used. Servers |
||||
_must not_ use this table to determine an HTTP status code to use; the mappings |
||||
are neither symmetric nor 1-to-1. |
||||
|
||||
| HTTP Status Code | gRPC Status Code | |
||||
|----------------------------|--------------------| |
||||
| 400 Bad Request | INTERNAL | |
||||
| 401 Unauthorized | UNAUTHENTICATED | |
||||
| 403 Forbidden | PERMISSION\_DENIED | |
||||
| 404 Not Found | UNIMPLEMENTED | |
||||
| 429 Too Many Requests | UNAVAILABLE | |
||||
| 502 Bad Gateway | UNAVAILABLE | |
||||
| 503 Service Unavailable | UNAVAILABLE | |
||||
| 504 Gateway Timeout | UNAVAILABLE | |
||||
| _All other codes_ | UNKNOWN | |
||||
|
||||
Technically, 1xx should have the entire header skipped and a subsequent header |
||||
be read. See RFC 7540 §8.1. |
||||
|
||||
200 is UNKNOWN because there should be a grpc-status in case of truly OK |
||||
response. |
@ -0,0 +1,4 @@ |
||||
The roots.pem file is periodically generated from: |
||||
https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt |
||||
using |
||||
https://github.com/agl/extract-nss-root-certs |
@ -0,0 +1,47 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H |
||||
#define GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H |
||||
|
||||
#include <grpc++/impl/codegen/status.h> |
||||
|
||||
namespace grpc { |
||||
|
||||
inline StatusCode GetCanonicalCode(const Status& status) { |
||||
return status.error_code(); |
||||
} |
||||
|
||||
} // namespace grpc
|
||||
|
||||
#endif // GRPCXX_IMPL_CODEGEN_STATUS_HELPER_H
|
@ -1,122 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015-2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_IMPL_CODEGEN_BYTE_BUFFER_H |
||||
#define GRPC_IMPL_CODEGEN_BYTE_BUFFER_H |
||||
|
||||
#include <grpc/impl/codegen/compression_types.h> |
||||
#include <grpc/impl/codegen/slice_buffer.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
typedef enum { |
||||
GRPC_BB_RAW |
||||
/* Future types may include GRPC_BB_PROTOBUF, etc. */ |
||||
} grpc_byte_buffer_type; |
||||
|
||||
struct grpc_byte_buffer { |
||||
void *reserved; |
||||
grpc_byte_buffer_type type; |
||||
union { |
||||
struct { |
||||
void *reserved[8]; |
||||
} reserved; |
||||
struct { |
||||
grpc_compression_algorithm compression; |
||||
gpr_slice_buffer slice_buffer; |
||||
} raw; |
||||
} data; |
||||
}; |
||||
typedef struct grpc_byte_buffer grpc_byte_buffer; |
||||
|
||||
/** Returns a RAW byte buffer instance over the given slices (up to \a nslices).
|
||||
* |
||||
* Increases the reference count for all \a slices processed. The user is |
||||
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ |
||||
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_create(gpr_slice *slices, |
||||
size_t nslices); |
||||
|
||||
/** Returns a *compressed* RAW byte buffer instance over the given slices (up to
|
||||
* \a nslices). The \a compression argument defines the compression algorithm |
||||
* used to generate the data in \a slices. |
||||
* |
||||
* Increases the reference count for all \a slices processed. The user is |
||||
* responsible for invoking grpc_byte_buffer_destroy on the returned instance.*/ |
||||
GRPCAPI grpc_byte_buffer *grpc_raw_compressed_byte_buffer_create( |
||||
gpr_slice *slices, size_t nslices, grpc_compression_algorithm compression); |
||||
|
||||
/** Copies input byte buffer \a bb.
|
||||
* |
||||
* Increases the reference count of all the source slices. The user is |
||||
* responsible for calling grpc_byte_buffer_destroy over the returned copy. */ |
||||
GRPCAPI grpc_byte_buffer *grpc_byte_buffer_copy(grpc_byte_buffer *bb); |
||||
|
||||
/** Returns the size of the given byte buffer, in bytes. */ |
||||
GRPCAPI size_t grpc_byte_buffer_length(grpc_byte_buffer *bb); |
||||
|
||||
/** Destroys \a byte_buffer deallocating all its memory. */ |
||||
GRPCAPI void grpc_byte_buffer_destroy(grpc_byte_buffer *byte_buffer); |
||||
|
||||
/** Reader for byte buffers. Iterates over slices in the byte buffer */ |
||||
struct grpc_byte_buffer_reader; |
||||
typedef struct grpc_byte_buffer_reader grpc_byte_buffer_reader; |
||||
|
||||
/** Initialize \a reader to read over \a buffer.
|
||||
* Returns 1 upon success, 0 otherwise. */ |
||||
GRPCAPI int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader *reader, |
||||
grpc_byte_buffer *buffer); |
||||
|
||||
/** Cleanup and destroy \a reader */ |
||||
GRPCAPI void grpc_byte_buffer_reader_destroy(grpc_byte_buffer_reader *reader); |
||||
|
||||
/** Updates \a slice with the next piece of data from from \a reader and returns
|
||||
* 1. Returns 0 at the end of the stream. Caller is responsible for calling |
||||
* gpr_slice_unref on the result. */ |
||||
GRPCAPI int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader *reader, |
||||
gpr_slice *slice); |
||||
|
||||
/** Merge all data from \a reader into single slice */ |
||||
GRPCAPI gpr_slice |
||||
grpc_byte_buffer_reader_readall(grpc_byte_buffer_reader *reader); |
||||
|
||||
/** Returns a RAW byte buffer instance from the output of \a reader. */ |
||||
GRPCAPI grpc_byte_buffer *grpc_raw_byte_buffer_from_reader( |
||||
grpc_byte_buffer_reader *reader); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GRPC_IMPL_CODEGEN_BYTE_BUFFER_H */ |
@ -0,0 +1,140 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_IMPL_CODEGEN_GPR_TYPES_H |
||||
#define GRPC_IMPL_CODEGEN_GPR_TYPES_H |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#include <stddef.h> |
||||
#include <stdint.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* The clocks we support. */ |
||||
typedef enum { |
||||
/* Monotonic clock. Epoch undefined. Always moves forwards. */ |
||||
GPR_CLOCK_MONOTONIC = 0, |
||||
/* Realtime clock. May jump forwards or backwards. Settable by
|
||||
the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */ |
||||
GPR_CLOCK_REALTIME, |
||||
/* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch
|
||||
undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */ |
||||
GPR_CLOCK_PRECISE, |
||||
/* Unmeasurable clock type: no base, created by taking the difference
|
||||
between two times */ |
||||
GPR_TIMESPAN |
||||
} gpr_clock_type; |
||||
|
||||
/* Analogous to struct timespec. On some machines, absolute times may be in
|
||||
* local time. */ |
||||
typedef struct gpr_timespec { |
||||
int64_t tv_sec; |
||||
int32_t tv_nsec; |
||||
/** Against which clock was this time measured? (or GPR_TIMESPAN if
|
||||
this is a relative time meaure) */ |
||||
gpr_clock_type clock_type; |
||||
} gpr_timespec; |
||||
|
||||
/* Slice API
|
||||
|
||||
A slice represents a contiguous reference counted array of bytes. |
||||
It is cheap to take references to a slice, and it is cheap to create a |
||||
slice pointing to a subset of another slice. |
||||
|
||||
The data-structure for slices is exposed here to allow non-gpr code to |
||||
build slices from whatever data they have available. |
||||
|
||||
When defining interfaces that handle slices, care should be taken to define |
||||
reference ownership semantics (who should call unref?) and mutability |
||||
constraints (is the callee allowed to modify the slice?) */ |
||||
|
||||
/* Reference count container for gpr_slice. Contains function pointers to
|
||||
increment and decrement reference counts. Implementations should cleanup |
||||
when the reference count drops to zero. |
||||
Typically client code should not touch this, and use gpr_slice_malloc, |
||||
gpr_slice_new, or gpr_slice_new_with_len instead. */ |
||||
typedef struct gpr_slice_refcount { |
||||
void (*ref)(void *); |
||||
void (*unref)(void *); |
||||
} gpr_slice_refcount; |
||||
|
||||
#define GPR_SLICE_INLINED_SIZE (sizeof(size_t) + sizeof(uint8_t *) - 1) |
||||
|
||||
/* A gpr_slice s, if initialized, represents the byte range
|
||||
s.bytes[0..s.length-1]. |
||||
|
||||
It can have an associated ref count which has a destruction routine to be run |
||||
when the ref count reaches zero (see gpr_slice_new() and grp_slice_unref()). |
||||
Multiple gpr_slice values may share a ref count. |
||||
|
||||
If the slice does not have a refcount, it represents an inlined small piece |
||||
of data that is copied by value. */ |
||||
typedef struct gpr_slice { |
||||
struct gpr_slice_refcount *refcount; |
||||
union { |
||||
struct { |
||||
uint8_t *bytes; |
||||
size_t length; |
||||
} refcounted; |
||||
struct { |
||||
uint8_t length; |
||||
uint8_t bytes[GPR_SLICE_INLINED_SIZE]; |
||||
} inlined; |
||||
} data; |
||||
} gpr_slice; |
||||
|
||||
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 |
||||
|
||||
/* Represents an expandable array of slices, to be interpreted as a
|
||||
single item. */ |
||||
typedef struct { |
||||
/* slices in the array */ |
||||
gpr_slice *slices; |
||||
/* the number of slices in the array */ |
||||
size_t count; |
||||
/* the number of slices allocated in the array */ |
||||
size_t capacity; |
||||
/* the combined length of all slices in the array */ |
||||
size_t length; |
||||
/* inlined elements to avoid allocations */ |
||||
gpr_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; |
||||
} gpr_slice_buffer; |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GRPC_IMPL_CODEGEN_GPR_TYPES_H */ |
@ -1,118 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_IMPL_CODEGEN_LOG_H |
||||
#define GRPC_IMPL_CODEGEN_LOG_H |
||||
|
||||
#include <inttypes.h> |
||||
#include <stdarg.h> |
||||
#include <stdlib.h> /* for abort() */ |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* GPR log API.
|
||||
|
||||
Usage (within grpc): |
||||
|
||||
int argument1 = 3; |
||||
char* argument2 = "hello"; |
||||
gpr_log(GPR_DEBUG, "format string %d", argument1); |
||||
gpr_log(GPR_INFO, "hello world"); |
||||
gpr_log(GPR_ERROR, "%d %s!!", argument1, argument2); */ |
||||
|
||||
/* The severity of a log message - use the #defines below when calling into
|
||||
gpr_log to additionally supply file and line data */ |
||||
typedef enum gpr_log_severity { |
||||
GPR_LOG_SEVERITY_DEBUG, |
||||
GPR_LOG_SEVERITY_INFO, |
||||
GPR_LOG_SEVERITY_ERROR |
||||
} gpr_log_severity; |
||||
|
||||
#define GPR_LOG_VERBOSITY_UNSET -1 |
||||
|
||||
/* Returns a string representation of the log severity */ |
||||
const char *gpr_log_severity_string(gpr_log_severity severity); |
||||
|
||||
/* Macros to build log contexts at various severity levels */ |
||||
#define GPR_DEBUG __FILE__, __LINE__, GPR_LOG_SEVERITY_DEBUG |
||||
#define GPR_INFO __FILE__, __LINE__, GPR_LOG_SEVERITY_INFO |
||||
#define GPR_ERROR __FILE__, __LINE__, GPR_LOG_SEVERITY_ERROR |
||||
|
||||
/* Log a message. It's advised to use GPR_xxx above to generate the context
|
||||
* for each message */ |
||||
GPRAPI void gpr_log(const char *file, int line, gpr_log_severity severity, |
||||
const char *format, ...) GPRC_PRINT_FORMAT_CHECK(4, 5); |
||||
|
||||
GPRAPI void gpr_log_message(const char *file, int line, |
||||
gpr_log_severity severity, const char *message); |
||||
|
||||
/* Set global log verbosity */ |
||||
GPRAPI void gpr_set_log_verbosity(gpr_log_severity min_severity_to_print); |
||||
|
||||
GPRAPI void gpr_log_verbosity_init(); |
||||
|
||||
/* Log overrides: applications can use this API to intercept logging calls
|
||||
and use their own implementations */ |
||||
|
||||
typedef struct { |
||||
const char *file; |
||||
int line; |
||||
gpr_log_severity severity; |
||||
const char *message; |
||||
} gpr_log_func_args; |
||||
|
||||
typedef void (*gpr_log_func)(gpr_log_func_args *args); |
||||
GPRAPI void gpr_set_log_function(gpr_log_func func); |
||||
|
||||
/* abort() the process if x is zero, having written a line to the log.
|
||||
|
||||
Intended for internal invariants. If the error can be recovered from, |
||||
without the possibility of corruption, or might best be reflected via |
||||
an exception in a higher-level language, consider returning error code. */ |
||||
#define GPR_ASSERT(x) \ |
||||
do { \
|
||||
if (!(x)) { \
|
||||
gpr_log(GPR_ERROR, "assertion failed: %s", #x); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0) |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GRPC_IMPL_CODEGEN_LOG_H */ |
@ -1,104 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_IMPL_CODEGEN_SLICE_BUFFER_H |
||||
#define GRPC_IMPL_CODEGEN_SLICE_BUFFER_H |
||||
|
||||
#include <grpc/impl/codegen/slice.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
#define GRPC_SLICE_BUFFER_INLINE_ELEMENTS 8 |
||||
|
||||
/* Represents an expandable array of slices, to be interpreted as a
|
||||
single item. */ |
||||
typedef struct { |
||||
/* slices in the array */ |
||||
gpr_slice *slices; |
||||
/* the number of slices in the array */ |
||||
size_t count; |
||||
/* the number of slices allocated in the array */ |
||||
size_t capacity; |
||||
/* the combined length of all slices in the array */ |
||||
size_t length; |
||||
/* inlined elements to avoid allocations */ |
||||
gpr_slice inlined[GRPC_SLICE_BUFFER_INLINE_ELEMENTS]; |
||||
} gpr_slice_buffer; |
||||
|
||||
/* initialize a slice buffer */ |
||||
GPRAPI void gpr_slice_buffer_init(gpr_slice_buffer *sb); |
||||
/* destroy a slice buffer - unrefs any held elements */ |
||||
GPRAPI void gpr_slice_buffer_destroy(gpr_slice_buffer *sb); |
||||
/* Add an element to a slice buffer - takes ownership of the slice.
|
||||
This function is allowed to concatenate the passed in slice to the end of |
||||
some other slice if desired by the slice buffer. */ |
||||
GPRAPI void gpr_slice_buffer_add(gpr_slice_buffer *sb, gpr_slice slice); |
||||
/* add an element to a slice buffer - takes ownership of the slice and returns
|
||||
the index of the slice. |
||||
Guarantees that the slice will not be concatenated at the end of another |
||||
slice (i.e. the data for this slice will begin at the first byte of the |
||||
slice at the returned index in sb->slices) |
||||
The implementation MAY decide to concatenate data at the end of a small |
||||
slice added in this fashion. */ |
||||
GPRAPI size_t gpr_slice_buffer_add_indexed(gpr_slice_buffer *sb, |
||||
gpr_slice slice); |
||||
GPRAPI void gpr_slice_buffer_addn(gpr_slice_buffer *sb, gpr_slice *slices, |
||||
size_t n); |
||||
/* add a very small (less than 8 bytes) amount of data to the end of a slice
|
||||
buffer: returns a pointer into which to add the data */ |
||||
GPRAPI uint8_t *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, size_t len); |
||||
/* pop the last buffer, but don't unref it */ |
||||
GPRAPI void gpr_slice_buffer_pop(gpr_slice_buffer *sb); |
||||
/* clear a slice buffer, unref all elements */ |
||||
GPRAPI void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb); |
||||
/* swap the contents of two slice buffers */ |
||||
GPRAPI void gpr_slice_buffer_swap(gpr_slice_buffer *a, gpr_slice_buffer *b); |
||||
/* move all of the elements of src into dst */ |
||||
GPRAPI void gpr_slice_buffer_move_into(gpr_slice_buffer *src, |
||||
gpr_slice_buffer *dst); |
||||
/* remove n bytes from the end of a slice buffer */ |
||||
GPRAPI void gpr_slice_buffer_trim_end(gpr_slice_buffer *src, size_t n, |
||||
gpr_slice_buffer *garbage); |
||||
/* move the first n bytes of src into dst */ |
||||
GPRAPI void gpr_slice_buffer_move_first(gpr_slice_buffer *src, size_t n, |
||||
gpr_slice_buffer *dst); |
||||
/* take the first slice in the slice buffer */ |
||||
GPRAPI gpr_slice gpr_slice_buffer_take_first(gpr_slice_buffer *src); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GRPC_IMPL_CODEGEN_SLICE_BUFFER_H */ |
@ -1,130 +0,0 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2015, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_IMPL_CODEGEN_TIME_H |
||||
#define GRPC_IMPL_CODEGEN_TIME_H |
||||
/* Time support.
|
||||
We use gpr_timespec, which is analogous to struct timespec. On some |
||||
machines, absolute times may be in local time. */ |
||||
|
||||
#include <grpc/impl/codegen/port_platform.h> |
||||
#include <stddef.h> |
||||
#include <time.h> |
||||
|
||||
#ifdef __cplusplus |
||||
extern "C" { |
||||
#endif |
||||
|
||||
/* The clocks we support. */ |
||||
typedef enum { |
||||
/* Monotonic clock. Epoch undefined. Always moves forwards. */ |
||||
GPR_CLOCK_MONOTONIC = 0, |
||||
/* Realtime clock. May jump forwards or backwards. Settable by
|
||||
the system administrator. Has its epoch at 0:00:00 UTC 1 Jan 1970. */ |
||||
GPR_CLOCK_REALTIME, |
||||
/* CPU cycle time obtained by rdtsc instruction on x86 platforms. Epoch
|
||||
undefined. Degrades to GPR_CLOCK_REALTIME on other platforms. */ |
||||
GPR_CLOCK_PRECISE, |
||||
/* Unmeasurable clock type: no base, created by taking the difference
|
||||
between two times */ |
||||
GPR_TIMESPAN |
||||
} gpr_clock_type; |
||||
|
||||
typedef struct gpr_timespec { |
||||
int64_t tv_sec; |
||||
int32_t tv_nsec; |
||||
/** Against which clock was this time measured? (or GPR_TIMESPAN if
|
||||
this is a relative time meaure) */ |
||||
gpr_clock_type clock_type; |
||||
} gpr_timespec; |
||||
|
||||
/* Time constants. */ |
||||
GPRAPI gpr_timespec |
||||
gpr_time_0(gpr_clock_type type); /* The zero time interval. */ |
||||
GPRAPI gpr_timespec gpr_inf_future(gpr_clock_type type); /* The far future */ |
||||
GPRAPI gpr_timespec gpr_inf_past(gpr_clock_type type); /* The far past. */ |
||||
|
||||
#define GPR_MS_PER_SEC 1000 |
||||
#define GPR_US_PER_SEC 1000000 |
||||
#define GPR_NS_PER_SEC 1000000000 |
||||
#define GPR_NS_PER_MS 1000000 |
||||
#define GPR_NS_PER_US 1000 |
||||
#define GPR_US_PER_MS 1000 |
||||
|
||||
/* initialize time subsystem */ |
||||
GPRAPI void gpr_time_init(void); |
||||
|
||||
/* Return the current time measured from the given clocks epoch. */ |
||||
GPRAPI gpr_timespec gpr_now(gpr_clock_type clock); |
||||
|
||||
/* Convert a timespec from one clock to another */ |
||||
GPRAPI gpr_timespec gpr_convert_clock_type(gpr_timespec t, |
||||
gpr_clock_type target_clock); |
||||
|
||||
/* Return -ve, 0, or +ve according to whether a < b, a == b, or a > b
|
||||
respectively. */ |
||||
GPRAPI int gpr_time_cmp(gpr_timespec a, gpr_timespec b); |
||||
|
||||
GPRAPI gpr_timespec gpr_time_max(gpr_timespec a, gpr_timespec b); |
||||
GPRAPI gpr_timespec gpr_time_min(gpr_timespec a, gpr_timespec b); |
||||
|
||||
/* Add and subtract times. Calculations saturate at infinities. */ |
||||
GPRAPI gpr_timespec gpr_time_add(gpr_timespec a, gpr_timespec b); |
||||
GPRAPI gpr_timespec gpr_time_sub(gpr_timespec a, gpr_timespec b); |
||||
|
||||
/* Return a timespec representing a given number of time units. INT64_MIN is
|
||||
interpreted as gpr_inf_past, and INT64_MAX as gpr_inf_future. */ |
||||
GPRAPI gpr_timespec gpr_time_from_micros(int64_t x, gpr_clock_type clock_type); |
||||
GPRAPI gpr_timespec gpr_time_from_nanos(int64_t x, gpr_clock_type clock_type); |
||||
GPRAPI gpr_timespec gpr_time_from_millis(int64_t x, gpr_clock_type clock_type); |
||||
GPRAPI gpr_timespec gpr_time_from_seconds(int64_t x, gpr_clock_type clock_type); |
||||
GPRAPI gpr_timespec gpr_time_from_minutes(int64_t x, gpr_clock_type clock_type); |
||||
GPRAPI gpr_timespec gpr_time_from_hours(int64_t x, gpr_clock_type clock_type); |
||||
|
||||
GPRAPI int32_t gpr_time_to_millis(gpr_timespec timespec); |
||||
|
||||
/* Return 1 if two times are equal or within threshold of each other,
|
||||
0 otherwise */ |
||||
GPRAPI int gpr_time_similar(gpr_timespec a, gpr_timespec b, |
||||
gpr_timespec threshold); |
||||
|
||||
/* Sleep until at least 'until' - an absolute timeout */ |
||||
GPRAPI void gpr_sleep_until(gpr_timespec until); |
||||
|
||||
GPRAPI double gpr_timespec_to_micros(gpr_timespec t); |
||||
|
||||
#ifdef __cplusplus |
||||
} |
||||
#endif |
||||
|
||||
#endif /* GRPC_IMPL_CODEGEN_TIME_H */ |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,293 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/iomgr/combiner.h" |
||||
|
||||
#include <string.h> |
||||
|
||||
#include <grpc/support/alloc.h> |
||||
#include <grpc/support/log.h> |
||||
|
||||
#include "src/core/lib/iomgr/workqueue.h" |
||||
#include "src/core/lib/profiling/timers.h" |
||||
|
||||
int grpc_combiner_trace = 0; |
||||
|
||||
#define GRPC_COMBINER_TRACE(fn) \ |
||||
do { \
|
||||
if (grpc_combiner_trace) { \
|
||||
fn; \
|
||||
} \
|
||||
} while (0) |
||||
|
||||
struct grpc_combiner { |
||||
grpc_workqueue *optional_workqueue; |
||||
gpr_mpscq queue; |
||||
// state is:
|
||||
// lower bit - zero if orphaned
|
||||
// other bits - number of items queued on the lock
|
||||
gpr_atm state; |
||||
bool take_async_break_before_final_list; |
||||
grpc_closure_list final_list; |
||||
grpc_closure continue_finishing; |
||||
}; |
||||
|
||||
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue) { |
||||
grpc_combiner *lock = gpr_malloc(sizeof(*lock)); |
||||
lock->optional_workqueue = optional_workqueue; |
||||
gpr_atm_no_barrier_store(&lock->state, 1); |
||||
gpr_mpscq_init(&lock->queue); |
||||
lock->take_async_break_before_final_list = false; |
||||
grpc_closure_list_init(&lock->final_list); |
||||
GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p create", lock)); |
||||
return lock; |
||||
} |
||||
|
||||
static void really_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, "C:%p really_destroy", lock)); |
||||
GPR_ASSERT(gpr_atm_no_barrier_load(&lock->state) == 0); |
||||
gpr_mpscq_destroy(&lock->queue); |
||||
GRPC_WORKQUEUE_UNREF(exec_ctx, lock->optional_workqueue, "combiner"); |
||||
gpr_free(lock); |
||||
} |
||||
|
||||
void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -1); |
||||
GRPC_COMBINER_TRACE(gpr_log( |
||||
GPR_DEBUG, "C:%p really_destroy old_state=%" PRIdPTR, lock, old_state)); |
||||
if (old_state == 1) { |
||||
really_destroy(exec_ctx, lock); |
||||
} |
||||
} |
||||
|
||||
static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); |
||||
static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); |
||||
|
||||
static void continue_finishing_mainline(grpc_exec_ctx *exec_ctx, void *arg, |
||||
grpc_error *error) { |
||||
GPR_TIMER_BEGIN("combiner.continue_executing_mainline", 0); |
||||
grpc_combiner *lock = arg; |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, "C:%p continue_finishing_mainline", lock)); |
||||
GPR_ASSERT(exec_ctx->active_combiner == NULL); |
||||
exec_ctx->active_combiner = lock; |
||||
if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); |
||||
GPR_ASSERT(exec_ctx->active_combiner == lock); |
||||
exec_ctx->active_combiner = NULL; |
||||
GPR_TIMER_END("combiner.continue_executing_mainline", 0); |
||||
} |
||||
|
||||
static void execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
GPR_TIMER_BEGIN("combiner.execute_final", 0); |
||||
grpc_closure *c = lock->final_list.head; |
||||
GPR_ASSERT(c != NULL); |
||||
grpc_closure_list_init(&lock->final_list); |
||||
lock->take_async_break_before_final_list = false; |
||||
int loops = 0; |
||||
while (c != NULL) { |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, "C:%p execute_final[%d] c=%p", lock, loops, c)); |
||||
grpc_closure *next = c->next_data.next; |
||||
grpc_error *error = c->error; |
||||
c->cb(exec_ctx, c->cb_arg, error); |
||||
GRPC_ERROR_UNREF(error); |
||||
c = next; |
||||
loops++; |
||||
} |
||||
GPR_TIMER_END("combiner.execute_final", 0); |
||||
} |
||||
|
||||
static void continue_executing_final(grpc_exec_ctx *exec_ctx, void *arg, |
||||
grpc_error *error) { |
||||
GPR_TIMER_BEGIN("combiner.continue_executing_final", 0); |
||||
grpc_combiner *lock = arg; |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, "C:%p continue_executing_final", lock)); |
||||
GPR_ASSERT(exec_ctx->active_combiner == NULL); |
||||
exec_ctx->active_combiner = lock; |
||||
// quick peek to see if new things have turned up on the queue: if so, go back
|
||||
// to executing them before the final list
|
||||
if ((gpr_atm_acq_load(&lock->state) >> 1) > 1) { |
||||
if (maybe_finish_one(exec_ctx, lock)) finish(exec_ctx, lock); |
||||
} else { |
||||
execute_final(exec_ctx, lock); |
||||
finish(exec_ctx, lock); |
||||
} |
||||
GPR_ASSERT(exec_ctx->active_combiner == lock); |
||||
exec_ctx->active_combiner = NULL; |
||||
GPR_TIMER_END("combiner.continue_executing_final", 0); |
||||
} |
||||
|
||||
static bool start_execute_final(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
GPR_TIMER_BEGIN("combiner.start_execute_final", 0); |
||||
GPR_ASSERT(exec_ctx->active_combiner == lock); |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, |
||||
"C:%p start_execute_final take_async_break_before_final_list=%d", |
||||
lock, lock->take_async_break_before_final_list)); |
||||
if (lock->take_async_break_before_final_list) { |
||||
grpc_closure_init(&lock->continue_finishing, continue_executing_final, |
||||
lock); |
||||
grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, |
||||
GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); |
||||
GPR_TIMER_END("combiner.start_execute_final", 0); |
||||
return false; |
||||
} else { |
||||
execute_final(exec_ctx, lock); |
||||
GPR_TIMER_END("combiner.start_execute_final", 0); |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
static bool maybe_finish_one(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
GPR_TIMER_BEGIN("combiner.maybe_finish_one", 0); |
||||
gpr_mpscq_node *n = gpr_mpscq_pop(&lock->queue); |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, "C:%p maybe_finish_one n=%p", lock, n)); |
||||
GPR_ASSERT(exec_ctx->active_combiner == lock); |
||||
if (n == NULL) { |
||||
// Queue is in an transiently inconsistent state: a new item is being queued
|
||||
// but is not visible to this thread yet.
|
||||
// Use this as a cue that we should go off and do something else for a while
|
||||
// (and come back later)
|
||||
grpc_closure_init(&lock->continue_finishing, continue_finishing_mainline, |
||||
lock); |
||||
grpc_exec_ctx_sched(exec_ctx, &lock->continue_finishing, GRPC_ERROR_NONE, |
||||
GRPC_WORKQUEUE_REF(lock->optional_workqueue, "sched")); |
||||
GPR_TIMER_END("combiner.maybe_finish_one", 0); |
||||
return false; |
||||
} |
||||
grpc_closure *cl = (grpc_closure *)n; |
||||
grpc_error *error = cl->error; |
||||
cl->cb(exec_ctx, cl->cb_arg, error); |
||||
GRPC_ERROR_UNREF(error); |
||||
GPR_TIMER_END("combiner.maybe_finish_one", 0); |
||||
return true; |
||||
} |
||||
|
||||
static void finish(grpc_exec_ctx *exec_ctx, grpc_combiner *lock) { |
||||
bool (*executor)(grpc_exec_ctx * exec_ctx, grpc_combiner * lock); |
||||
GPR_TIMER_BEGIN("combiner.finish", 0); |
||||
int loops = 0; |
||||
do { |
||||
executor = maybe_finish_one; |
||||
gpr_atm old_state = gpr_atm_full_fetch_add(&lock->state, -2); |
||||
GRPC_COMBINER_TRACE(gpr_log(GPR_DEBUG, |
||||
"C:%p finish[%d] old_state=%" PRIdPTR, lock, |
||||
loops, old_state)); |
||||
switch (old_state) { |
||||
default: |
||||
// we have multiple queued work items: just continue executing them
|
||||
break; |
||||
case 5: // we're down to one queued item: if it's the final list we
|
||||
case 4: // should do that
|
||||
if (!grpc_closure_list_empty(lock->final_list)) { |
||||
executor = start_execute_final; |
||||
} |
||||
break; |
||||
case 3: // had one count, one unorphaned --> unlocked unorphaned
|
||||
GPR_TIMER_END("combiner.finish", 0); |
||||
return; |
||||
case 2: // and one count, one orphaned --> unlocked and orphaned
|
||||
really_destroy(exec_ctx, lock); |
||||
GPR_TIMER_END("combiner.finish", 0); |
||||
return; |
||||
case 1: |
||||
case 0: |
||||
// these values are illegal - representing an already unlocked or
|
||||
// deleted lock
|
||||
GPR_UNREACHABLE_CODE(return ); |
||||
} |
||||
loops++; |
||||
} while (executor(exec_ctx, lock)); |
||||
GPR_TIMER_END("combiner.finish", 0); |
||||
} |
||||
|
||||
void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
||||
grpc_closure *cl, grpc_error *error) { |
||||
GRPC_COMBINER_TRACE( |
||||
gpr_log(GPR_DEBUG, "C:%p grpc_combiner_execute c=%p", lock, cl)); |
||||
GPR_TIMER_BEGIN("combiner.execute", 0); |
||||
gpr_atm last = gpr_atm_full_fetch_add(&lock->state, 2); |
||||
GPR_ASSERT(last & 1); // ensure lock has not been destroyed
|
||||
if (last == 1) { |
||||
exec_ctx->active_combiner = lock; |
||||
GPR_TIMER_BEGIN("combiner.execute_first_cb", 0); |
||||
cl->cb(exec_ctx, cl->cb_arg, error); |
||||
GPR_TIMER_END("combiner.execute_first_cb", 0); |
||||
GRPC_ERROR_UNREF(error); |
||||
finish(exec_ctx, lock); |
||||
GPR_ASSERT(exec_ctx->active_combiner == lock); |
||||
exec_ctx->active_combiner = NULL; |
||||
} else { |
||||
cl->error = error; |
||||
gpr_mpscq_push(&lock->queue, &cl->next_data.atm_next); |
||||
} |
||||
GPR_TIMER_END("combiner.execute", 0); |
||||
} |
||||
|
||||
static void enqueue_finally(grpc_exec_ctx *exec_ctx, void *closure, |
||||
grpc_error *error) { |
||||
grpc_combiner_execute_finally(exec_ctx, exec_ctx->active_combiner, closure, |
||||
GRPC_ERROR_REF(error), false); |
||||
} |
||||
|
||||
void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
||||
grpc_closure *closure, grpc_error *error, |
||||
bool force_async_break) { |
||||
GRPC_COMBINER_TRACE(gpr_log( |
||||
GPR_DEBUG, |
||||
"C:%p grpc_combiner_execute_finally c=%p force_async_break=%d; ac=%p", |
||||
lock, closure, force_async_break, exec_ctx->active_combiner)); |
||||
GPR_TIMER_BEGIN("combiner.execute_finally", 0); |
||||
if (exec_ctx->active_combiner != lock) { |
||||
GPR_TIMER_MARK("slowpath", 0); |
||||
grpc_combiner_execute(exec_ctx, lock, |
||||
grpc_closure_create(enqueue_finally, closure), error); |
||||
GPR_TIMER_END("combiner.execute_finally", 0); |
||||
return; |
||||
} |
||||
|
||||
if (force_async_break) { |
||||
lock->take_async_break_before_final_list = true; |
||||
} |
||||
if (grpc_closure_list_empty(lock->final_list)) { |
||||
gpr_atm_full_fetch_add(&lock->state, 2); |
||||
} |
||||
grpc_closure_list_append(&lock->final_list, closure, error); |
||||
GPR_TIMER_END("combiner.execute_finally", 0); |
||||
} |
||||
|
||||
void grpc_combiner_force_async_finally(grpc_combiner *lock) { |
||||
lock->take_async_break_before_final_list = true; |
||||
} |
@ -0,0 +1,71 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#ifndef GRPC_CORE_LIB_IOMGR_COMBINER_H |
||||
#define GRPC_CORE_LIB_IOMGR_COMBINER_H |
||||
|
||||
#include <stddef.h> |
||||
|
||||
#include <grpc/support/atm.h> |
||||
#include "src/core/lib/iomgr/exec_ctx.h" |
||||
#include "src/core/lib/support/mpscq.h" |
||||
|
||||
// Provides serialized access to some resource.
|
||||
// Each action queued on a combiner is executed serially in a borrowed thread.
|
||||
// The actual thread executing actions may change over time (but there will only
|
||||
// every be one at a time).
|
||||
|
||||
// Initialize the lock, with an optional workqueue to shift load to when
|
||||
// necessary
|
||||
grpc_combiner *grpc_combiner_create(grpc_workqueue *optional_workqueue); |
||||
// Destroy the lock
|
||||
void grpc_combiner_destroy(grpc_exec_ctx *exec_ctx, grpc_combiner *lock); |
||||
// Execute \a action within the lock.
|
||||
void grpc_combiner_execute(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
||||
grpc_closure *closure, grpc_error *error); |
||||
// Execute \a action within the lock just prior to unlocking.
|
||||
// if \a hint_async_break is true, the combiner tries to hand execution to
|
||||
// another thread before finishing the primary queue of combined closures and
|
||||
// executing the finally list.
|
||||
// Deprecation warning: \a hint_async_break will be removed in a future version
|
||||
// Takes a very slow and round-about path if not called from a
|
||||
// grpc_combiner_execute closure.
|
||||
void grpc_combiner_execute_finally(grpc_exec_ctx *exec_ctx, grpc_combiner *lock, |
||||
grpc_closure *closure, grpc_error *error, |
||||
bool hint_async_break); |
||||
// Deprecated: force the finally list execution onto another thread
|
||||
void grpc_combiner_force_async_finally(grpc_combiner *lock); |
||||
|
||||
extern int grpc_combiner_trace; |
||||
|
||||
#endif /* GRPC_CORE_LIB_IOMGR_COMBINER_H */ |
@ -0,0 +1,83 @@ |
||||
/*
|
||||
* |
||||
* Copyright 2016, Google Inc. |
||||
* All rights reserved. |
||||
* |
||||
* Redistribution and use in source and binary forms, with or without |
||||
* modification, are permitted provided that the following conditions are |
||||
* met: |
||||
* |
||||
* * Redistributions of source code must retain the above copyright |
||||
* notice, this list of conditions and the following disclaimer. |
||||
* * Redistributions in binary form must reproduce the above |
||||
* copyright notice, this list of conditions and the following disclaimer |
||||
* in the documentation and/or other materials provided with the |
||||
* distribution. |
||||
* * Neither the name of Google Inc. nor the names of its |
||||
* contributors may be used to endorse or promote products derived from |
||||
* this software without specific prior written permission. |
||||
* |
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||||
* |
||||
*/ |
||||
|
||||
#include "src/core/lib/support/mpscq.h" |
||||
|
||||
#include <grpc/support/log.h> |
||||
|
||||
void gpr_mpscq_init(gpr_mpscq *q) { |
||||
gpr_atm_no_barrier_store(&q->head, (gpr_atm)&q->stub); |
||||
q->tail = &q->stub; |
||||
gpr_atm_no_barrier_store(&q->stub.next, (gpr_atm)NULL); |
||||
} |
||||
|
||||
void gpr_mpscq_destroy(gpr_mpscq *q) { |
||||
GPR_ASSERT(gpr_atm_no_barrier_load(&q->head) == (gpr_atm)&q->stub); |
||||
GPR_ASSERT(q->tail == &q->stub); |
||||
} |
||||
|
||||
void gpr_mpscq_push(gpr_mpscq *q, gpr_mpscq_node *n) { |
||||
gpr_atm_no_barrier_store(&n->next, (gpr_atm)NULL); |
||||
gpr_mpscq_node *prev = |
||||
(gpr_mpscq_node *)gpr_atm_full_xchg(&q->head, (gpr_atm)n); |
||||
gpr_atm_rel_store(&prev->next, (gpr_atm)n); |
||||
} |
||||
|
||||
gpr_mpscq_node *gpr_mpscq_pop(gpr_mpscq *q) { |
||||
gpr_mpscq_node *tail = q->tail; |
||||
gpr_mpscq_node *next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); |
||||
if (tail == &q->stub) { |
||||
// indicates the list is actually (ephemerally) empty
|
||||
if (next == NULL) return NULL; |
||||
q->tail = next; |
||||
tail = next; |
||||
next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); |
||||
} |
||||
if (next != NULL) { |
||||
q->tail = next; |
||||
return tail; |
||||
} |
||||
gpr_mpscq_node *head = (gpr_mpscq_node *)gpr_atm_acq_load(&q->head); |
||||
if (tail != head) { |
||||
// indicates a retry is in order: we're still adding
|
||||
return NULL; |
||||
} |
||||
gpr_mpscq_push(q, &q->stub); |
||||
next = (gpr_mpscq_node *)gpr_atm_acq_load(&tail->next); |
||||
if (next != NULL) { |
||||
q->tail = next; |
||||
return tail; |
||||
} |
||||
// indicates a retry is in order: we're still adding
|
||||
return NULL; |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue