-
Notifications
You must be signed in to change notification settings - Fork 191
Add private data support for deferred_response #144
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,32 +18,65 @@ | |
| USA | ||
| */ | ||
|
|
||
| #include <atomic> | ||
| #include <httpserver.hpp> | ||
|
|
||
| using namespace httpserver; | ||
|
|
||
| static int counter = 0; | ||
| std::atomic<int> reqid; | ||
|
|
||
| ssize_t test_callback (char* buf, size_t max) { | ||
| if (counter == 2) { | ||
| typedef struct { | ||
| int reqid; | ||
| } connection; | ||
|
|
||
| ssize_t test_callback (void* data, char* buf, size_t max) { | ||
| int reqid; | ||
| if (data == nullptr) { | ||
| reqid = -1; | ||
| } else { | ||
| reqid = static_cast<connection*>(data)->reqid; | ||
| } | ||
|
|
||
| // only first 5 connections can be established | ||
| if (reqid >= 5) { | ||
| return -1; | ||
| } | ||
| else { | ||
| memset(buf, 0, max); | ||
| strcat(buf, " test "); | ||
| counter++; | ||
| return std::string(buf).size(); | ||
|
|
||
| // respond corresponding request IDs to the clients | ||
| std::string str = ""; | ||
| str += std::to_string(reqid) + " "; | ||
| memset(buf, 0, max); | ||
| std::copy(str.begin(), str.end(), buf); | ||
|
|
||
| // keep sending reqid | ||
| sleep(1); | ||
| return (ssize_t)max; | ||
| } | ||
|
|
||
| void test_cleanup (void** data) | ||
| { | ||
| if (*data != nullptr) { | ||
| delete static_cast<connection*>(*data); | ||
| } | ||
| data = nullptr; | ||
| } | ||
|
|
||
| class deferred_resource : public http_resource { | ||
| public: | ||
| const std::shared_ptr<http_response> render_GET(const http_request& req) { | ||
| return std::shared_ptr<deferred_response>(new deferred_response(test_callback, "cycle callback response")); | ||
| // private data of new connections | ||
| auto priv_data = new connection(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please, refrain from using "auto" for now |
||
| priv_data->reqid = reqid++; | ||
|
|
||
| auto response = std::make_shared<deferred_response>(test_callback, priv_data, test_cleanup, | ||
| "cycle callback response"); | ||
| return response; | ||
| } | ||
| }; | ||
|
|
||
| int main(int argc, char** argv) { | ||
| reqid.store(0); | ||
|
|
||
| webserver ws = create_webserver(8080); | ||
|
|
||
| deferred_resource hwr; | ||
|
|
@@ -52,4 +85,3 @@ int main(int argc, char** argv) { | |
|
|
||
| return 0; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,26 +35,33 @@ namespace details | |
| ssize_t cb(void*, uint64_t, char*, size_t); | ||
| }; | ||
|
|
||
| typedef ssize_t(*cycle_callback_ptr)(char*, size_t); | ||
| typedef ssize_t(*cycle_callback_ptr)(void*, char*, size_t); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When I was thinking about this feature, I tried to figure how we could avoid the "void*" for the type. To be honest this is probably one of those cases where "seeing it after it is written might help". I was thinking we could use a template type to define the first parameter and a "shared_ptr" to pass it through. This would save us from having to use the "void*" and, ideally, from having the cleanup function entirely. To be honest, I would convert the currently existing "char*" into a shared_ptr if we are perturbing the interface. |
||
| typedef void(*cleanup_callback_ptr)(void**); | ||
|
|
||
| class deferred_response : public string_response | ||
| { | ||
| public: | ||
| explicit deferred_response( | ||
| cycle_callback_ptr cycle_callback, | ||
| void* priv_data = nullptr, | ||
| cleanup_callback_ptr cleanup_callback = nullptr, | ||
| const std::string& content = "", | ||
| int response_code = http::http_utils::http_ok, | ||
| const std::string& content_type = http::http_utils::text_plain | ||
| ): | ||
| string_response(content, response_code, content_type), | ||
| cycle_callback(cycle_callback), | ||
| priv_data(priv_data), | ||
| cleanup_callback(cleanup_callback), | ||
| completed(false) | ||
| { | ||
| } | ||
|
|
||
| deferred_response(const deferred_response& other): | ||
| string_response(other), | ||
| cycle_callback(other.cycle_callback), | ||
| priv_data(other.priv_data), | ||
| cleanup_callback(other.cleanup_callback), | ||
| completed(other.completed) | ||
| { | ||
| } | ||
|
|
@@ -73,6 +80,8 @@ class deferred_response : public string_response | |
| (string_response&) (*this) = b; | ||
| this->cycle_callback = b.cycle_callback; | ||
| this->completed = b.completed; | ||
| this->priv_data = b.priv_data; | ||
| this->cleanup_callback = b.cleanup_callback; | ||
|
|
||
| return *this; | ||
| } | ||
|
|
@@ -84,18 +93,25 @@ class deferred_response : public string_response | |
| (string_response&) (*this) = std::move(b); | ||
| this->cycle_callback = std::move(b.cycle_callback); | ||
| this->completed = b.completed; | ||
| this->priv_data = b.priv_data; | ||
| this->cleanup_callback = b.cleanup_callback; | ||
|
|
||
| return *this; | ||
| } | ||
|
|
||
| ~deferred_response() | ||
| { | ||
| if (priv_data != nullptr) { | ||
| cleanup_callback(&priv_data); | ||
| } | ||
| } | ||
|
|
||
| MHD_Response* get_raw_response(); | ||
| void decorate_response(MHD_Response* response); | ||
| private: | ||
| cycle_callback_ptr cycle_callback; | ||
| void* priv_data; | ||
| cleanup_callback_ptr cleanup_callback; | ||
| bool completed; | ||
|
|
||
| friend ssize_t details::cb(void* cls, uint64_t pos, char* buf, size_t max); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,7 +47,7 @@ size_t writefunc(void *ptr, size_t size, size_t nmemb, std::string *s) | |
|
|
||
| static int counter = 0; | ||
|
|
||
| ssize_t test_callback (char* buf, size_t max) | ||
| ssize_t test_callback (void*, char* buf, size_t max) | ||
| { | ||
| if (counter == 2) | ||
| { | ||
|
|
@@ -67,7 +67,8 @@ class deferred_resource : public http_resource | |
| public: | ||
| const shared_ptr<http_response> render_GET(const http_request& req) | ||
| { | ||
| return shared_ptr<deferred_response>(new deferred_response(test_callback, "cycle callback response")); | ||
| return shared_ptr<deferred_response>(new deferred_response(test_callback, nullptr, nullptr, | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should have a separate resource and a separate that is used to verify that the new functionality is working fine. |
||
| "cycle callback response")); | ||
| } | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for typedefs - we can just have a named struct