Loop::defer and almost working async streaming

This commit is contained in:
Alex Hultman
2018-09-23 21:48:29 +02:00
parent 2fb87b67c7
commit 8106a0f628
6 changed files with 123 additions and 17 deletions
+7
View File
@@ -168,6 +168,13 @@ private:
// todo: share this path with HttpResponse::write (it is exatly the same logic!)
while (true) {
auto [msg_more, chunk] = httpResponseData->outStream(httpResponseData->offset);
if (chunk.length() == 0) {
std::cout << "onwritable paused!" << std::endl;
httpResponseData->state |= HttpResponseData<SSL>::HTTP_PAUSED_STREAM_OUT;
break;
}
int written = asyncSocket->mergeDrain(chunk);
httpResponseData->offset += written;
// this is not correct, we can reach the end!
+28 -1
View File
@@ -96,6 +96,7 @@ public:
/* Do nothing if not even paused */
if (!(httpResponseData->state & HttpResponseData<SSL>::HTTP_PAUSED_STREAM_OUT)) {
std::cout << "Resue called but we are not even in paused state!" << std::endl;
return;
}
@@ -104,11 +105,33 @@ public:
/* Remove paused status */
httpResponseData->state &= ~HttpResponseData<SSL>::HTTP_PAUSED_STREAM_OUT;
if (chunk.length()) {
/*if (chunk.length()) {
int written = AsyncSocket<SSL>::write(chunk.data(), chunk.length(), true);
if (written == chunk.length()) {
// pull a new chunk from the callback (basically call onWritable)
std::cout << "Wrote everything off!" << std::endl;
}
}*/
AsyncSocket<SSL> *asyncSocket = this;
// again, this path is shared with onwritable, write and here!
while (true) {
auto [msg_more, chunk] = httpResponseData->outStream(httpResponseData->offset);
// break on pause!
if (chunk.length() == 0) {
std::cout << "Resume paused!" << std::endl;
httpResponseData->state |= HttpResponseData<SSL>::HTTP_PAUSED_STREAM_OUT;
break;
}
int written = asyncSocket->mergeDrain(chunk);
httpResponseData->offset += written;
// this is not correct, we can reach the end!
if (written < chunk.length()) {
break;
}
}
@@ -164,6 +187,10 @@ public:
/* Disable timeout and mark this stream as paused (important to silence spurious onWritable events) */
AsyncSocket<SSL>::timeout(0);
httpResponseData->state |= HttpResponseData<SSL>::HTTP_PAUSED_STREAM_OUT;
// forgot about this path, if we sent things off and then ended up pausing!
httpResponseData->offset = offset;
httpResponseData->outStream = cb;
}
return;
}
+31 -1
View File
@@ -7,13 +7,29 @@
#include <libusockets.h>
#include <thread>
#include <iostream>
namespace uWS {
struct Loop {
private:
static void wakeupCb(us_loop *loop) {
std::cout << "wakeupCB called" << std::endl;
LoopData *loopData = (LoopData *) us_loop_ext(loop);
/* Swap current deferQueue */
loopData->deferMutex.lock();
int oldDeferQueue = loopData->currentDeferQueue;
loopData->currentDeferQueue = (loopData->currentDeferQueue + 1) % 2;
loopData->deferMutex.unlock();
/* Drain the queue */
for (auto &x : loopData->deferQueues[oldDeferQueue]) {
x();
}
loopData->deferQueues[oldDeferQueue].clear();
}
static void preCb(us_loop *loop) {
@@ -63,6 +79,20 @@ public:
us_loop_free((us_loop *) this);
}
/* Defer this callback on Loop's thread of execution */
void defer(std::function<void()> cb) {
LoopData *loopData = (LoopData *) us_loop_ext((us_loop *) this);
std::cout << "defer called" << std::endl;
//if (std::thread::get_id() == ) // todo: add fast path for same thread id
loopData->deferMutex.lock();
loopData->deferQueues[loopData->currentDeferQueue].emplace_back(cb);
loopData->deferMutex.unlock();
std::cout << "us_wakeup_loop called" << std::endl;
us_wakeup_loop((us_loop *) this);
}
/* Actively block and run this loop */
void run() {
us_loop_run((us_loop *) this);
+13
View File
@@ -1,8 +1,19 @@
#ifndef LOOPDATA_H
#define LOOPDATA_H
#include <thread>
#include <functional>
#include <vector>
#include <mutex>
namespace uWS {
struct LoopData {
friend struct Loop;
private:
std::mutex deferMutex;
int currentDeferQueue = 0;
std::vector<std::function<void()>> deferQueues[2];
public:
/* Good 16k for SSL perf. */
@@ -14,4 +25,6 @@ public:
bool corked = false;
};
}
#endif // LOOPDATA_H