mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-15 07:00:05 -05:00
graph: new scheduling model
Make explicit links between elements that are used to activate the next element in the graph. Make subgraphs a special regular node. Make a link from the subgraph children to the parent so that the subgraph completes when all the children completed. Implement a single process function in plugins Remove many messages in the client node
This commit is contained in:
parent
9b0a880afb
commit
33a322b96e
36 changed files with 401 additions and 750 deletions
|
|
@ -140,8 +140,7 @@ static inline int spa_graph_impl_run(void *data)
|
|||
|
||||
static const struct spa_graph_callbacks spa_graph_impl_default = {
|
||||
SPA_VERSION_GRAPH_CALLBACKS,
|
||||
.need_input = spa_graph_impl_need_input,
|
||||
.have_output = spa_graph_impl_have_output,
|
||||
.trigger = spa_graph_impl_have_output,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -36,121 +36,6 @@ static inline void spa_graph_data_init(struct spa_graph_data *data,
|
|||
data->graph = graph;
|
||||
}
|
||||
|
||||
static inline int spa_graph_trigger(struct spa_graph *g, struct spa_graph_node *node)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
spa_debug("node %p: pending %d required %d", node,
|
||||
node->state->pending, node->state->required);
|
||||
|
||||
if (node->state->pending == 0) {
|
||||
spa_debug("node %p: nothing pending", node);
|
||||
return node->state->status;
|
||||
}
|
||||
|
||||
val = __atomic_sub_fetch(&node->state->pending, 1, __ATOMIC_SEQ_CST);
|
||||
if (val == 0)
|
||||
spa_graph_node_process(node);
|
||||
|
||||
return node->state->status;
|
||||
}
|
||||
|
||||
static inline int spa_graph_impl_need_input(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
#if 0
|
||||
struct spa_graph_data *d = (struct spa_graph_data *) data;
|
||||
struct spa_list queue, pending;
|
||||
struct spa_graph_node *n, *pn;
|
||||
struct spa_graph_port *p, *pp;
|
||||
|
||||
spa_debug("node %p start pull", node);
|
||||
|
||||
spa_list_init(&queue);
|
||||
spa_list_init(&pending);
|
||||
|
||||
node->state->status = SPA_STATUS_NEED_BUFFER;
|
||||
|
||||
if (node->sched_link.next == NULL)
|
||||
spa_list_append(&queue, &node->sched_link);
|
||||
|
||||
while (!spa_list_is_empty(&queue)) {
|
||||
|
||||
n = spa_list_first(&queue, struct spa_graph_node, sched_link);
|
||||
spa_list_remove(&n->sched_link);
|
||||
n->sched_link.next = NULL;
|
||||
|
||||
n->state->pending = n->state->required + 1;
|
||||
spa_debug("node %p: add %d %d status %d", n,
|
||||
n->state->pending, n->state->required,
|
||||
n->state->status);
|
||||
|
||||
spa_list_prepend(&pending, &n->sched_link);
|
||||
|
||||
if (n->state->status == SPA_STATUS_HAVE_BUFFER)
|
||||
continue;
|
||||
|
||||
spa_list_for_each(p, &n->ports[SPA_DIRECTION_INPUT], link) {
|
||||
pp = p->peer;
|
||||
if (pp == NULL)
|
||||
continue;
|
||||
pn = pp->node;
|
||||
|
||||
spa_debug("node %p: %p in io:%d state:%d %p", n, pn, pp->io->status,
|
||||
pn->state->status, pn->sched_link.next);
|
||||
|
||||
if (pn->sched_link.next != NULL)
|
||||
continue;
|
||||
|
||||
if (pp->io->status == SPA_STATUS_NEED_BUFFER &&
|
||||
pn->state->status == SPA_STATUS_HAVE_BUFFER) {
|
||||
pn->state->status = spa_graph_node_process(pn);
|
||||
} else {
|
||||
n->state->pending--;
|
||||
}
|
||||
spa_list_append(&queue, &pn->sched_link);
|
||||
}
|
||||
}
|
||||
while (!spa_list_is_empty(&pending)) {
|
||||
n = spa_list_first(&pending, struct spa_graph_node, sched_link);
|
||||
spa_list_remove(&n->sched_link);
|
||||
n->sched_link.next = NULL;
|
||||
|
||||
spa_debug("schedule node %p: %d", n, n->state->status);
|
||||
spa_graph_trigger(d->graph, n);
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spa_graph_impl_have_output(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_data *d = (struct spa_graph_data *) data;
|
||||
struct spa_graph_port *p;
|
||||
|
||||
spa_debug("node %p start push", node);
|
||||
|
||||
spa_list_for_each(p, &node->ports[SPA_DIRECTION_OUTPUT], link)
|
||||
if (p->peer)
|
||||
spa_graph_trigger(d->graph, p->peer->node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void spa_graph_impl_add_graph(struct spa_graph *g, struct spa_list *pending)
|
||||
{
|
||||
struct spa_graph_node *n;
|
||||
struct spa_graph *sg;
|
||||
|
||||
spa_list_for_each(n, &g->nodes, link) {
|
||||
n->state->pending = n->state->required + 1;
|
||||
spa_debug("graph %p node %p: add %d %d status %d", g, n,
|
||||
n->state->pending, n->state->required, n->state->status);
|
||||
spa_list_append(pending, &n->sched_link);
|
||||
}
|
||||
spa_list_for_each(sg, &g->subgraphs, link)
|
||||
spa_graph_impl_add_graph(sg, pending);
|
||||
}
|
||||
|
||||
static inline int spa_graph_impl_run(void *data)
|
||||
{
|
||||
struct spa_graph_data *d = (struct spa_graph_data *) data;
|
||||
|
|
@ -159,22 +44,43 @@ static inline int spa_graph_impl_run(void *data)
|
|||
struct spa_list pending;
|
||||
|
||||
spa_debug("graph %p run", d->graph);
|
||||
spa_graph_state_reset(g->state);
|
||||
|
||||
spa_list_init(&pending);
|
||||
|
||||
spa_graph_impl_add_graph(g, &pending);
|
||||
spa_list_for_each(n, &g->nodes, link) {
|
||||
struct spa_graph_state *s = n->state;
|
||||
|
||||
spa_graph_state_reset(s);
|
||||
|
||||
spa_debug("graph %p node %p: add %d status %d", g, n, s->pending, s->status);
|
||||
|
||||
if (s->pending == 0)
|
||||
spa_list_append(&pending, &n->sched_link);
|
||||
}
|
||||
spa_list_for_each_safe(n, tmp, &pending, sched_link)
|
||||
spa_graph_trigger(d->graph, n);
|
||||
spa_graph_node_process(n);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spa_graph_impl_finish(void *data)
|
||||
{
|
||||
struct spa_graph_data *d = (struct spa_graph_data *) data;
|
||||
struct spa_graph *g = d->graph;
|
||||
|
||||
spa_debug("graph %p finish", d->graph);
|
||||
|
||||
if (g->parent)
|
||||
spa_graph_node_trigger(g->parent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct spa_graph_callbacks spa_graph_impl_default = {
|
||||
SPA_VERSION_GRAPH_CALLBACKS,
|
||||
.need_input = spa_graph_impl_need_input,
|
||||
.have_output = spa_graph_impl_have_output,
|
||||
.run = spa_graph_impl_run,
|
||||
.finish = spa_graph_impl_finish,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
|||
|
|
@ -35,62 +35,91 @@ extern "C" {
|
|||
|
||||
struct spa_graph;
|
||||
struct spa_graph_node;
|
||||
struct spa_graph_link;
|
||||
struct spa_graph_port;
|
||||
|
||||
struct spa_graph_state {
|
||||
int status; /**< current status */
|
||||
uint32_t required; /**< required number of signals */
|
||||
uint32_t pending; /**< number of pending signals */
|
||||
};
|
||||
|
||||
static inline void spa_graph_state_reset(struct spa_graph_state *state)
|
||||
{
|
||||
state->pending = state->required;
|
||||
}
|
||||
|
||||
struct spa_graph_link {
|
||||
struct spa_list link;
|
||||
struct spa_graph_state *state;
|
||||
int (*signal) (void *data, void *target);
|
||||
void *signal_data;
|
||||
};
|
||||
|
||||
#define spa_graph_link_signal(l,t) ((l)->signal((l)->signal_data,(t)))
|
||||
|
||||
static inline int spa_graph_link_trigger(struct spa_graph_link *link, void *target)
|
||||
{
|
||||
struct spa_graph_state *state = link->state;
|
||||
|
||||
if (state->pending == 0) {
|
||||
spa_debug("link %p: nothing pending", link);
|
||||
} else {
|
||||
spa_debug("link %p: pending %d required %d", link,
|
||||
state->pending, state->required);
|
||||
if (__atomic_sub_fetch(&state->pending, 1, __ATOMIC_SEQ_CST) == 0)
|
||||
spa_graph_link_signal(link, target);
|
||||
}
|
||||
return state->status;
|
||||
}
|
||||
|
||||
struct spa_graph_callbacks {
|
||||
#define SPA_VERSION_GRAPH_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
int (*need_input) (void *data, struct spa_graph_node *node);
|
||||
int (*have_output) (void *data, struct spa_graph_node *node);
|
||||
int (*run) (void *data);
|
||||
int (*finish) (void *data);
|
||||
};
|
||||
#define spa_graph_run(g) ((g)->callbacks->run((g)->callbacks_data))
|
||||
#define spa_graph_finish(g) ((g)->callbacks->finish((g)->callbacks_data))
|
||||
|
||||
struct spa_graph {
|
||||
struct spa_list link; /* link for subgraph */
|
||||
#define SPA_GRAPH_FLAG_DRIVER (1 << 0)
|
||||
uint32_t flags; /* flags */
|
||||
struct spa_graph *parent; /* parent graph or NULL when driver */
|
||||
struct spa_graph_node *parent; /* parent node or NULL when driver */
|
||||
struct spa_graph_state *state; /* state of graph */
|
||||
struct spa_list nodes; /* list of nodes of this graph */
|
||||
struct spa_list subgraphs; /* list of subgraphs */
|
||||
const struct spa_graph_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
};
|
||||
|
||||
#define spa_graph_need_input(g,n) ((g)->callbacks->need_input((g)->callbacks_data, (n)))
|
||||
#define spa_graph_have_output(g,n) ((g)->callbacks->have_output((g)->callbacks_data, (n)))
|
||||
#define spa_graph_run(g) ((g)->callbacks->run((g)->callbacks_data))
|
||||
|
||||
struct spa_graph_state {
|
||||
int status; /**< status of the node */
|
||||
uint32_t required; /**< required number of input nodes */
|
||||
uint32_t pending; /**< number of input nodes pending */
|
||||
};
|
||||
|
||||
struct spa_graph_node_callbacks {
|
||||
#define SPA_VERSION_GRAPH_NODE_CALLBACKS 0
|
||||
uint32_t version;
|
||||
|
||||
int (*trigger) (void *data, struct spa_graph_node *node);
|
||||
int (*process) (void *data, struct spa_graph_node *node);
|
||||
int (*reuse_buffer) (void *data, struct spa_graph_node *node,
|
||||
uint32_t port_id, uint32_t buffer_id);
|
||||
};
|
||||
#define spa_graph_node_trigger(n) ((n)->callbacks->trigger((n)->callbacks_data,(n)))
|
||||
#define spa_graph_node_process(n) ((n)->callbacks->process((n)->callbacks_data,(n)))
|
||||
#define spa_graph_node_reuse_buffer(n,p,i) ((n)->callbacks->reuse_buffer((n)->callbacks_data,(n),(p),(i)))
|
||||
|
||||
struct spa_graph_node {
|
||||
struct spa_list link; /**< link in graph nodes list */
|
||||
struct spa_graph *graph; /**< owner graph */
|
||||
struct spa_list ports[2]; /**< list of input and output ports */
|
||||
#define SPA_GRAPH_NODE_FLAG_ASYNC (1 << 0)
|
||||
struct spa_list links; /**< list of links */
|
||||
uint32_t flags; /**< node flags */
|
||||
struct spa_graph_state *state; /**< state of the node */
|
||||
struct spa_graph_link graph_link; /**< link in graph */
|
||||
struct spa_graph *subgraph; /**< subgraph or NULL */
|
||||
const struct spa_graph_node_callbacks *callbacks;
|
||||
void *callbacks_data;
|
||||
struct spa_list sched_link; /**< link for scheduler */
|
||||
void *scheduler_data; /**< scheduler private data */
|
||||
};
|
||||
|
||||
#define spa_graph_node_process(n) ((n)->callbacks->process((n)->callbacks_data, (n)))
|
||||
#define spa_graph_node_reuse_buffer(n,p,i) ((n)->callbacks->reuse_buffer((n)->callbacks_data, (n),(p),(i)))
|
||||
|
||||
struct spa_graph_port {
|
||||
struct spa_list link; /**< link in node port list */
|
||||
|
|
@ -100,14 +129,27 @@ struct spa_graph_port {
|
|||
uint32_t flags; /**< port flags */
|
||||
struct spa_io_buffers *io; /**< io area of the port */
|
||||
struct spa_graph_port *peer; /**< peer */
|
||||
void *scheduler_data; /**< scheduler private data */
|
||||
};
|
||||
|
||||
static inline void spa_graph_init(struct spa_graph *graph)
|
||||
static inline int spa_graph_link_signal_node(void *data, void *arg)
|
||||
{
|
||||
struct spa_graph_node *node = data;
|
||||
return spa_graph_node_process(node);
|
||||
}
|
||||
|
||||
static inline int spa_graph_link_signal_graph(void *data, void *arg)
|
||||
{
|
||||
struct spa_graph_node *node = data;
|
||||
if (node->graph)
|
||||
spa_graph_finish(node->graph);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void spa_graph_init(struct spa_graph *graph, struct spa_graph_state *state)
|
||||
{
|
||||
spa_list_init(&graph->nodes);
|
||||
spa_list_init(&graph->subgraphs);
|
||||
graph->flags = 0;
|
||||
graph->state = state;
|
||||
spa_debug("graph %p init", graph);
|
||||
}
|
||||
|
||||
|
|
@ -120,25 +162,22 @@ spa_graph_set_callbacks(struct spa_graph *graph,
|
|||
graph->callbacks_data = data;
|
||||
}
|
||||
|
||||
static inline struct spa_graph *spa_graph_find_root(struct spa_graph *graph)
|
||||
static inline void
|
||||
spa_graph_link_add(struct spa_graph_node *out,
|
||||
struct spa_graph_state *state,
|
||||
struct spa_graph_link *link)
|
||||
{
|
||||
while (graph->parent)
|
||||
graph = graph->parent;
|
||||
return graph;
|
||||
spa_debug("node %p add link %p to node %p", out, link, state);
|
||||
link->state = state;
|
||||
state->required++;
|
||||
spa_list_append(&out->links, &link->link);
|
||||
}
|
||||
|
||||
static inline void spa_graph_add_subgraph(struct spa_graph *graph, struct spa_graph *subgraph)
|
||||
static inline void spa_graph_link_remove(struct spa_graph_link *link)
|
||||
{
|
||||
subgraph->parent = graph;
|
||||
spa_list_append(&graph->subgraphs, &subgraph->link);
|
||||
spa_debug("graph %p add subgraph %p", graph, subgraph);
|
||||
}
|
||||
|
||||
static inline void spa_graph_remove_subgraph(struct spa_graph *subgraph)
|
||||
{
|
||||
subgraph->parent = NULL;
|
||||
spa_list_remove(&subgraph->link);
|
||||
spa_debug("graph %p remove subgraph", subgraph);
|
||||
spa_debug("link %p remove", link);
|
||||
link->state->required--;
|
||||
spa_list_remove(&link->link);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -146,13 +185,47 @@ spa_graph_node_init(struct spa_graph_node *node, struct spa_graph_state *state)
|
|||
{
|
||||
spa_list_init(&node->ports[SPA_DIRECTION_INPUT]);
|
||||
spa_list_init(&node->ports[SPA_DIRECTION_OUTPUT]);
|
||||
spa_list_init(&node->links);
|
||||
node->flags = 0;
|
||||
node->subgraph = NULL;
|
||||
node->state = state;
|
||||
node->state->required = node->state->pending = 0;
|
||||
node->state->status = SPA_STATUS_OK;
|
||||
node->graph_link.signal = spa_graph_link_signal_graph;
|
||||
node->graph_link.signal_data = node;
|
||||
spa_debug("node %p init", node);
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_impl_trigger(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph_link *l, *t;
|
||||
spa_debug("node %p trigger", node);
|
||||
spa_list_for_each_safe(l, t, &node->links, link)
|
||||
spa_graph_link_trigger(l, node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_impl_sub_process(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph *graph = node->subgraph;
|
||||
spa_debug("node %p: sub process %p", node, graph);
|
||||
return spa_graph_run(graph);
|
||||
}
|
||||
|
||||
static const struct spa_graph_node_callbacks spa_graph_node_sub_impl_default = {
|
||||
SPA_VERSION_GRAPH_NODE_CALLBACKS,
|
||||
.trigger = spa_graph_node_impl_trigger,
|
||||
.process = spa_graph_node_impl_sub_process,
|
||||
};
|
||||
|
||||
static inline void spa_graph_node_set_subgraph(struct spa_graph_node *node,
|
||||
struct spa_graph *subgraph)
|
||||
{
|
||||
node->subgraph = subgraph;
|
||||
subgraph->parent = node;
|
||||
spa_debug("node %p set subgraph %p", node, subgraph);
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_node_set_callbacks(struct spa_graph_node *node,
|
||||
const struct spa_graph_node_callbacks *callbacks,
|
||||
|
|
@ -167,11 +240,19 @@ spa_graph_node_add(struct spa_graph *graph,
|
|||
struct spa_graph_node *node)
|
||||
{
|
||||
node->graph = graph;
|
||||
node->sched_link.next = NULL;
|
||||
spa_list_append(&graph->nodes, &node->link);
|
||||
spa_graph_link_add(node, graph->state, &node->graph_link);
|
||||
spa_debug("node %p add to graph %p", node, graph);
|
||||
}
|
||||
|
||||
static inline void spa_graph_node_remove(struct spa_graph_node *node)
|
||||
{
|
||||
spa_debug("node %p remove", node);
|
||||
spa_graph_link_remove(&node->graph_link);
|
||||
spa_list_remove(&node->link);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
spa_graph_port_init(struct spa_graph_port *port,
|
||||
enum spa_direction direction,
|
||||
|
|
@ -195,19 +276,10 @@ spa_graph_port_add(struct spa_graph_node *node,
|
|||
spa_list_append(&node->ports[port->direction], &port->link);
|
||||
}
|
||||
|
||||
static inline void spa_graph_node_remove(struct spa_graph_node *node)
|
||||
{
|
||||
spa_debug("node %p remove", node);
|
||||
spa_list_remove(&node->link);
|
||||
if (node->sched_link.next)
|
||||
spa_list_remove(&node->sched_link);
|
||||
}
|
||||
|
||||
static inline void spa_graph_port_remove(struct spa_graph_port *port)
|
||||
{
|
||||
spa_debug("port %p remove", port);
|
||||
spa_list_remove(&port->link);
|
||||
port->node = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
|
@ -216,49 +288,27 @@ spa_graph_port_link(struct spa_graph_port *out, struct spa_graph_port *in)
|
|||
spa_debug("port %p link to %p %p %p", out, in, in->node, in->node->state);
|
||||
out->peer = in;
|
||||
in->peer = out;
|
||||
if (in->direction == SPA_DIRECTION_INPUT)
|
||||
in->node->state->required++;
|
||||
else
|
||||
out->node->state->required++;
|
||||
}
|
||||
|
||||
static inline void
|
||||
spa_graph_port_unlink(struct spa_graph_port *port)
|
||||
{
|
||||
struct spa_graph_port *out, *in;
|
||||
|
||||
spa_debug("port %p unlink from %p", port, port->peer);
|
||||
if (port->direction == SPA_DIRECTION_INPUT) {
|
||||
in = port;
|
||||
out = port->peer;
|
||||
} else {
|
||||
out = port;
|
||||
in = port->peer;
|
||||
}
|
||||
|
||||
if (out && in) {
|
||||
in->node->state->required--;
|
||||
out->peer = NULL;
|
||||
in->peer = NULL;
|
||||
if (port->peer) {
|
||||
port->peer->peer = NULL;
|
||||
port->peer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_impl_process(void *data, struct spa_graph_node *node)
|
||||
{
|
||||
struct spa_graph *g = node->graph;
|
||||
struct spa_node *n = data;
|
||||
int res = 0;
|
||||
|
||||
res = spa_node_process(n);
|
||||
spa_debug("node %p: process %d", node, node->state->status);
|
||||
if ((node->state->status = spa_node_process(n)) == SPA_STATUS_HAVE_BUFFER)
|
||||
spa_graph_node_trigger(node);
|
||||
|
||||
spa_debug("node %p: process %d", node, res);
|
||||
|
||||
node->state->status = res;
|
||||
|
||||
if (res == SPA_STATUS_HAVE_BUFFER)
|
||||
spa_graph_have_output(g, node);
|
||||
|
||||
return res;
|
||||
return node->state->status;
|
||||
}
|
||||
|
||||
static inline int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_node *node,
|
||||
|
|
@ -270,6 +320,7 @@ static inline int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_
|
|||
|
||||
static const struct spa_graph_node_callbacks spa_graph_node_impl_default = {
|
||||
SPA_VERSION_GRAPH_NODE_CALLBACKS,
|
||||
.trigger = spa_graph_node_impl_trigger,
|
||||
.process = spa_graph_node_impl_process,
|
||||
.reuse_buffer = spa_graph_node_impl_reuse_buffer,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -83,23 +83,13 @@ struct spa_node_callbacks {
|
|||
/**
|
||||
* \param node a spa_node
|
||||
*
|
||||
* The node needs more input. This callback is called from the
|
||||
* The node is ready for processing. This callback is called from the
|
||||
* data thread.
|
||||
*
|
||||
* When this function is NULL, synchronous operation is requested
|
||||
* on the input ports.
|
||||
* on the ports.
|
||||
*/
|
||||
void (*need_input) (void *data);
|
||||
/**
|
||||
* \param node a spa_node
|
||||
*
|
||||
* The node has output input. This callback is called from the
|
||||
* data thread.
|
||||
*
|
||||
* When this function is NULL, synchronous operation is requested
|
||||
* on the output ports.
|
||||
*/
|
||||
void (*have_output) (void *data);
|
||||
void (*process) (void *data, int state);
|
||||
|
||||
/**
|
||||
* \param node a spa_node
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ extern "C" {
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#define SPA_ASYNC_BIT (1 << 30)
|
||||
|
|
@ -155,9 +156,21 @@ struct spa_fraction {
|
|||
#define spa_assert_se(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) \
|
||||
fprintf(stderr, "'%s' failed at %s:%u %s()", \
|
||||
#expr , __FILE__, __LINE__, __func__); \
|
||||
abort(); \
|
||||
} while (false)
|
||||
|
||||
#define spa_assert(expr) \
|
||||
do { \
|
||||
if (SPA_UNLIKELY(!(expr))) { \
|
||||
fprintf(stderr, "'%s' failed at %s:%u %s()", \
|
||||
#expr , __FILE__, __LINE__, __func__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
|
||||
/* Does exactly nothing */
|
||||
#define spa_nop() do {} while (false)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue