Skip to content
This repository has been archived by the owner on Jun 12, 2018. It is now read-only.

multithreads in http #220

Open
suxunbin opened this issue Apr 18, 2018 · 25 comments
Open

multithreads in http #220

suxunbin opened this issue Apr 18, 2018 · 25 comments

Comments

@suxunbin
Copy link

I find a problem when I use server_http.hpp(old version) in http.
qq 20180418201558
"response" is a shared_ptr<HttpServer:: Response> type. In this way, *response can send data to the client.
However,
qq 20180418201650
qq 20180418202443
When I let "Res" equal to "response",*response can not send data to the client.

Why I can't pass a shared_ptr<HttpServer:: Response> to another.

@eidheim
Copy link
Owner

eidheim commented Apr 18, 2018

What is the signature of query_thread?

@suxunbin
Copy link
Author

4
6
7
8

10
12
Part of ghttp.cpp

@suxunbin
Copy link
Author

shared_ptr<HttpServer:: Request> is Ok
But
shared_ptr<HttpServer:: Response> is no use when I use pointer assignment

@suxunbin
Copy link
Author

1

@eidheim
Copy link
Owner

eidheim commented Apr 18, 2018

I could not see anything wrong after a quick look, but making a copy of the response shared_ptr should work fine. I'll have another look Tomorrow if you have not figured it out by then.

@eidheim
Copy link
Owner

eidheim commented Apr 18, 2018

Ah, the problem seems to be that the Res shared_ptr is kept alive too long. The response is sent when the shared_ptr is destructed, and it seems like your Res object is kept alive in a scope higher than the scope of the handler.

@suxunbin
Copy link
Author

Yes,I want to store the Res object in order to use it after the handler.
And I find maybe connection between server and client is not broken.
But only *response this ostream doesn't send data to the client.
So make a copy of the response shared_ptr would lead the ostream confusion?

@suxunbin
Copy link
Author

This is the Response's define in server_http.hpp

qq 20180419113348

@eidheim
Copy link
Owner

eidheim commented Apr 19, 2018

In that case, you need to use Response::send to send the data you have added to the response stream to the client. See https://github.com/eidheim/Simple-Web-Server/blob/master/http_examples.cpp#L183 for an example.

@suxunbin
Copy link
Author

server_http.txt

@suxunbin
Copy link
Author

This is the server_http.hpp that I used.
*response will send the data to the client itself,will it?

@eidheim
Copy link
Owner

eidheim commented Apr 19, 2018

Sadly that would be too inefficient. The data is sent when Response::send is called, or when the Response object within the shared_ptr is destroyed.

@suxunbin
Copy link
Author

Actually,I'm writing a threadpool.
1
pool.create() create a daemon thread to continuously get task from tasklines and run query_thread().
Where, tasklines is a global variable
3
2
4
5
However, I find that if I don't sleep(10) in query_handler(), the daemon thread will not get response and request object.
In other words, if I leave query_handler() scope, the daemon thread(detached from the server) will not get response and request object.

@suxunbin
Copy link
Author

When I am in query_handler() scope,obviously the response and request object are valid wherever they are referred(for example, Task , tasklines, the daemon thread). However, when I leave query_handler() scope, the response and request object are invalid wherever they are referred.
And I want the response and request object to be kept alive in a scope higher than the scope of the handler.(for example , the location of pool.create() )

@suxunbin
Copy link
Author

3
Can I have a way that when I leave the scope,the response and request object are still alive?
I hope that server.resource doesn't destroy the response and request object when they leave the scope.

@suxunbin
Copy link
Author

I have read the https://github.com/eidheim/Simple-Web-Server/blob/master/http_examples.cpp#L183 example.
6
My purpose is to use referrence of the response and request object on the location in the picture.
In other words, I hope to store referrence of the response and request object as global variables in order that other threads can use them.

@eidheim
Copy link
Owner

eidheim commented Apr 19, 2018

The purpose of shared_ptr's is typically to extend the lifetime of an object. When you pass the shared_ptr to query_thread, the shared_ptr is copied and thus the object's lifetime is extended. You should in general not need to store shared_ptr's globally.

@suxunbin
Copy link
Author

However, I need thread scheduling. So I only store them in query_handler().
Another thread is responsible for query_thread().
I can't directly pass the shared_ptr to query_thread() in query_handler().
I need another thread to know all the shared_ptrs in order to assign.

@suxunbin
Copy link
Author

For example,if there are 60 queries but I only have 30 threads in the threadpool. If I directly pass the shared_ptr to query_thread().Then there are 30 shared_ptr that can't pass.I must store them.
So how should I store the rest shared_ptr so that they are still valid when they leave the scope.

@eidheim
Copy link
Owner

eidheim commented Apr 19, 2018

Regarding a thread pool of size 30, here is a simplified example of how I would implement this using asio:

#include "server_http.hpp"

class Workers {
public:
  boost::asio::io_service service;

private:
  boost::asio::io_service::work work;
  std::vector<std::thread> threads;

public:
  Workers(size_t number_of_threads) : work(service) {
    for(size_t c = 0; c < number_of_threads; ++c) {
      threads.emplace_back([this] {
        service.run();
      });
    }
  }
};

using namespace std;

using HttpServer = SimpleWeb::Server<SimpleWeb::HTTP>;

int main() {
  Workers workers(30);

  HttpServer server;
  server.config.port = 8080;

  server.default_resource["GET"] = [&workers](shared_ptr<HttpServer::Response> response, shared_ptr<HttpServer::Request> /*request*/) {
    workers.service.post([response] {
      this_thread::sleep_for(chrono::seconds(5)); // Simulate time-consuming work
      response->write("Work done");
    });
  };

  server.start();
}

The response-shared_ptr is here copied by capture in workers.service.post and thus kept alive throughout the handler.

@suxunbin
Copy link
Author

In this way,if 30 threads are running,then what about the new shared_ptr ?

@suxunbin
Copy link
Author

If use workers.service.post, how should I sort these handlers in io_service.
I could not handle thest tasks according to the order of their entry.

@suxunbin
Copy link
Author

11
13
I use the example you give me. But client gets nothing.

@suxunbin
Copy link
Author

14
If I don't use workers.service.post(), client can directly get the data.

@suxunbin
Copy link
Author

So, when I leave this scope, the response shared_ptr becomes invalid.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants