Loop::defer and almost working async streaming
This commit is contained in:
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user