/
zOMGdev
/
cppcms
Обзор
Документация
Войти
/
zOMGdev
/
cppcms
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v2.0.0.beta1
tests/pool_test.cpp
369 строк
9 KB
Artyom Beilis
Switch from booster::shared_ptr/weak_ptr to std::ones
11 авг 2020, 22:57
11 авг 2020, 22:57
dfc88bd
Код
Авторство
О чём код?
/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com> // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #include <cppcms/service.h> #include <cppcms/application.h> #include <cppcms/applications_pool.h> #include <cppcms/http_request.h> #include <cppcms/http_response.h> #include <cppcms/http_context.h> #include <cppcms/url_dispatcher.h> #include <cppcms/mount_point.h> #include <booster/aio/deadline_timer.h> #include <booster/posix_time.h> #include <cppcms/json.h> #include <booster/thread.h> #include <iostream> #include "client.h" #include <sstream> #include <booster/log.h> #include "test.h" #include <assert.h> int g_fail; #define TESTNT(x) do { if(x) break; std::cerr << "FAIL: " #x " in line: " << __LINE__ << std::endl; g_fail = 1; return; } while(0) booster::thread_specific_ptr<int> g_thread_id; booster::mutex g_id_lock; int g_thread_id_counter=1000; struct thread_submitter { thread_submitter(cppcms::service &srv) : srv_(&srv) {} void operator()() const { runner r(*srv_); booster::thread t(r); t.detach(); } cppcms::service *srv_; }; void set_thread_id(int v) { g_thread_id.reset(new int(v)); } int get_thread_id() { if(g_thread_id.get()==0) { booster::unique_lock<booster::mutex> guard(g_id_lock); int new_id = ++g_thread_id_counter; set_thread_id(new_id); } return *g_thread_id; } class counter { typedef booster::unique_lock<booster::mutex> guard; counter() : current(0), max(0), total(0) { } public: static counter *instance(std::string const &name) { static const int max = 20; static int curr; static counter all[max]; for(int i=0;i<curr;i++) if(all[i].name==name) return all + i; assert(curr < max); all[curr].name = name; return all + curr++; } void print(std::ostream &out) { guard g(lock_); out<< "name="<<name<<"\n" "current="<<current<<"\n" "total="<<total<<"\n" "max="<<max; } std::string name; int current; int max; int total; int inc() { guard g(lock_); int r = ++total; current++; if(max < current) max = current; return r; } void dec() { guard g(lock_); current--; } private: booster::mutex lock_; }; class unit_test : public cppcms::application { public: unit_test(cppcms::service &s,counter *c) : cppcms::application(s), c_(c), id_(0), original_thread_id_(0) { id_ = c_->inc(); original_thread_id_ = get_thread_id(); } ~unit_test() { c_->dec(); } void main(std::string path) { double sleep_for = atof(request().get("sleep").c_str()); BOOSTER_DEBUG("cppcms") << "--------- GOT " << path << " for " << sleep_for << " from " << id_ << " in " << get_thread_id(); booster::ptime::sleep(booster::ptime::from_number(sleep_for)); std::ostringstream ss; ss << "url=" << request().script_name() << path << "\n" "thread_id=" << get_thread_id() << "\n" "original_thread_id=" << original_thread_id_ << "\n" "app_id="<<id_; BOOSTER_DEBUG("cppcms") << "RESPONSE " << path << " from " << id_ << "\n" << ss.str() ; response().out() << ss.str(); } private: counter *c_; int id_; int original_thread_id_; }; std::map<std::string,booster::weak_ptr<cppcms::application_specific_pool> > weak_pools; class tester : public cppcms::application { public: tester(cppcms::service &srv) : cppcms::application(srv) {} void main(std::string name) { if(name=="/stats") counter::instance(request().get("id"))->print(response().out()); else if(name=="/unmount") { std::string id = request().get("id"); bool exists_before = bool(weak_pools[id].lock()); service().applications_pool().unmount(weak_pools[id]); bool exists_after = bool(weak_pools[id].lock()); response().out()<<"unmount=" << id << "\n" "before="<<exists_before <<"\n" "after="<<exists_after; } else if(name=="/install") { app_ = new unit_test(service(),counter::instance("/async/temporary")); service().applications_pool().mount(app_,cppcms::mount_point("/async","/temporary",0)); response().out()<<"install=1"; } else if(name=="/uninstall") { response().out()<<"install=0"; app_ = 0; } } private: booster::intrusive_ptr<cppcms::application> app_; }; struct marker { marker(std::string const &name) : name_(name) {} booster::shared_ptr<cppcms::application_specific_pool> const &operator | (booster::shared_ptr<cppcms::application_specific_pool> const &in) { weak_pools[name_] = in; return in; } std::string name_; }; struct pools { booster::weak_ptr<cppcms::application_specific_pool> sync,async; bool async_requested; pools() : async_requested(false) {} }; class sender : public cppcms::application { public: struct src_prop { bool src_async; bool src_created; bool src_to_app; }; sender(cppcms::service &srv,pools *p) : cppcms::application(srv), pools_(p) { } void main(std::string url) { if(url!="/sender") { src_prop *p = context().get_specific<src_prop>(); TESTNT(p); response().out() << "async=" << is_asynchronous() << "\n" "src_async=" << p->src_async <<"\n" "src_created="<< p->src_created <<"\n" "src_to_app=" << p->src_to_app <<"\n" "path=" << url<<"\n" ; return; } src_prop *p=new src_prop(); context().reset_specific<src_prop>(p); bool to_app = request().get("to_app")=="1"; p->src_to_app = to_app; p->src_async = is_asynchronous(); p->src_created = false; booster::shared_ptr<cppcms::application_specific_pool> tgt; if(request().get("to")=="sync") tgt = pools_->sync.lock(); else tgt = pools_->async.lock(); booster::shared_ptr<cppcms::http::context> ctx = release_context(); TESTNT(tgt); if(!to_app) { ctx->submit_to_pool(tgt,"/pool"); return; } booster::intrusive_ptr<cppcms::application> app; app =tgt->asynchronous_application_by_io_service(service().get_io_service()); if(!app) { app = tgt->asynchronous_application_by_io_service(service().get_io_service(),service()); p->src_created=true; } TESTNT(app); ctx->submit_to_asynchronous_application(app,"/app"); } private: pools *pools_; }; int main(int argc,char **argv) { try { { using cppcms::mount_point; cppcms::service srv(argc,argv); set_thread_id(1); srv.applications_pool().mount( marker("/sync") | cppcms::create_pool<unit_test>(counter::instance("/sync")), mount_point("/sync","",0), cppcms::app::synchronous); srv.applications_pool().mount( cppcms::create_pool<unit_test>(counter::instance("/sync/work")), mount_point("/sync","/work",0), cppcms::app::synchronous); srv.applications_pool().mount( marker("/sync/prepopulated") | cppcms::create_pool<unit_test>(counter::instance("/sync/prepopulated")), mount_point("/sync","/prepopulated",0), cppcms::app::synchronous | cppcms::app::prepopulated); srv.applications_pool().mount( marker("/sync/tss") | cppcms::create_pool<unit_test>(counter::instance("/sync/tss")), mount_point("/sync","/tss",0), cppcms::app::synchronous | cppcms::app::thread_specific); srv.applications_pool().mount( cppcms::applications_factory<unit_test>(counter::instance("/sync/legacy")), mount_point("/sync","/legacy",0)); srv.applications_pool().mount( marker("/async") | cppcms::create_pool<unit_test>(counter::instance("/async")), mount_point("/async","",0), cppcms::app::asynchronous); srv.applications_pool().mount( marker("/async/prepopulated") | cppcms::create_pool<unit_test>(counter::instance("/async/prepopulated")), mount_point("/async","/prepopulated",0), cppcms::app::asynchronous | cppcms::app::prepopulated); booster::intrusive_ptr<cppcms::application> app = new unit_test(srv,counter::instance("/async/legacy")); srv.applications_pool().mount( app, mount_point("/async","/legacy",0)); counter::instance("/async/temporary"); srv.applications_pool().mount(cppcms::create_pool<tester>(),mount_point("/test"),cppcms::app::asynchronous); pools p; { booster::shared_ptr<cppcms::application_specific_pool> tmp; srv.applications_pool().mount( (tmp=cppcms::create_pool<sender>(&p)), mount_point("/async","/sender",0), cppcms::app::asynchronous); p.async = tmp; } { booster::shared_ptr<cppcms::application_specific_pool> tmp; srv.applications_pool().mount( (tmp=cppcms::create_pool<sender>(&p)), mount_point("/sync","/sender",0), cppcms::app::synchronous); p.sync = tmp; } srv.after_fork(thread_submitter(srv)); srv.run(); weak_pools.clear(); } std::cout << "Test all deleted" << std::endl; TEST(counter::instance("/sync")->current == 0); TEST(counter::instance("/sync/prepopulated")->current == 0); TEST(counter::instance("/sync/tss")->current == 0); TEST(counter::instance("/sync/legacy")->current == 0); TEST(counter::instance("/async")->current == 0); TEST(counter::instance("/async/prepopulated")->current == 0); TEST(counter::instance("/async/legacy")->current == 0); std::cout << "Done" << std::endl; } catch(std::exception const &e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } if(run_ok && !g_fail) { std::cout << "Full Test: Ok" << std::endl; return EXIT_SUCCESS; } else { std::cout << "FAILED" << std::endl; return EXIT_FAILURE; } }