vitastor/ringloop.cpp

89 lines
2.1 KiB
C++
Raw Permalink Normal View History

2019-11-05 02:12:04 +03:00
#include "ringloop.h"
ring_loop_t::ring_loop_t(int qd)
{
int ret = io_uring_queue_init(qd, &ring, 0);
2019-11-05 02:12:04 +03:00
if (ret < 0)
{
throw std::runtime_error(std::string("io_uring_queue_init: ") + strerror(-ret));
2019-11-05 02:12:04 +03:00
}
free_ring_data_ptr = *ring.cq.kring_entries;
ring_datas = (struct ring_data_t*)malloc(sizeof(ring_data_t) * free_ring_data_ptr);
free_ring_data = (int*)malloc(sizeof(int) * free_ring_data_ptr);
if (!ring_datas || !free_ring_data)
2019-11-05 02:12:04 +03:00
{
throw std::bad_alloc();
2019-11-05 02:12:04 +03:00
}
for (int i = 0; i < free_ring_data_ptr; i++)
{
free_ring_data[i] = i;
}
2019-11-05 02:12:04 +03:00
}
ring_loop_t::~ring_loop_t()
{
free(free_ring_data);
free(ring_datas);
2019-11-17 17:45:39 +03:00
io_uring_queue_exit(&ring);
2019-11-05 02:12:04 +03:00
}
int ring_loop_t::register_consumer(ring_consumer_t & consumer)
{
consumer.number = consumers.size();
consumers.push_back(consumer);
return consumer.number;
}
2019-12-13 22:53:59 +03:00
void ring_loop_t::wakeup()
2019-11-05 02:12:04 +03:00
{
2019-11-18 14:08:11 +03:00
loop_again = true;
}
void ring_loop_t::unregister_consumer(ring_consumer_t & consumer)
{
if (consumer.number >= 0 && consumer.number < consumers.size())
2019-11-05 02:12:04 +03:00
{
2019-11-18 14:08:11 +03:00
consumers[consumer.number].loop = NULL;
consumer.number = -1;
2019-11-05 02:12:04 +03:00
}
}
2019-11-18 14:08:11 +03:00
void ring_loop_t::loop()
2019-11-05 02:12:04 +03:00
{
struct io_uring_cqe *cqe;
2019-11-17 17:45:39 +03:00
while (!io_uring_peek_cqe(&ring, &cqe))
2019-11-05 02:12:04 +03:00
{
struct ring_data_t *d = (struct ring_data_t*)cqe->user_data;
if (d->callback)
2019-11-05 02:12:04 +03:00
{
2019-11-17 22:26:55 +03:00
d->res = cqe->res;
d->callback(d);
2019-11-05 02:12:04 +03:00
}
free_ring_data[free_ring_data_ptr++] = d - ring_datas;
io_uring_cqe_seen(&ring, cqe);
2019-11-05 02:12:04 +03:00
}
2019-11-18 14:08:11 +03:00
do
2019-11-17 17:45:39 +03:00
{
2019-11-18 14:08:11 +03:00
loop_again = false;
for (int i = 0; i < consumers.size(); i++)
{
consumers[i].loop();
}
} while (loop_again);
2019-11-05 02:12:04 +03:00
}
unsigned ring_loop_t::save()
{
return ring.sq.sqe_tail;
}
void ring_loop_t::restore(unsigned sqe_tail)
{
assert(ring.sq.sqe_tail >= sqe_tail);
for (unsigned i = sqe_tail; i < ring.sq.sqe_tail; i++)
{
free_ring_data[free_ring_data_ptr++] = ((ring_data_t*)ring.sq.sqes[i & *ring.sq.kring_mask].user_data) - ring_datas;
}
ring.sq.sqe_tail = sqe_tail;
}