#ifdef USE_PCH #include "pch.h" #else #include #include #include #include #include using namespace std; #include "sitecing/component_so.h" #include "sitecing/sitecing_util.h" #endif namespace sitecing { /* * component_so */ component_so::component_so(const string& soname) : dl(NULL), sofile(soname) { if(stat(sofile.c_str(),&stso)) throw konforka::exception(CODEPOINT,"failed to stat() shared object"); file_lock lock(sofile+".lock"); dl = dlopen(sofile.c_str(),RTLD_LAZY); lock.unlock(); if(!dl) throw konforka::exception(CODEPOINT,"failed to dlopen: "+string(dlerror())); egg = (egg_t)dlsym(dl,"_egg"); if(!egg) throw konforka::exception(CODEPOINT,"failed to dlsym: "+string(dlerror())); } component_so::~component_so() { for(free_chickens_t::iterator i=chickens_free.begin();i!=chickens_free.end();i++) delete *i; chickens_free.clear(); if(!chickens_used.empty()) throw konforka::exception(CODEPOINT,"attempt to destroy the component in use"); dlclose(dl); } bool component_so::is_uptodate() const { struct stat st; if(stat(sofile.c_str(),&st)) throw konforka::exception(CODEPOINT,"failed to stat() shared object"); return stso.st_mtime==st.st_mtime; } acomponent* component_so::allocate_chicken() { acomponent *rv; if(!chickens_free.empty()) { rv = chickens_free.front(); chickens_free.pop_front(); }else{ rv = (*egg)(); } assert(chickens_used.find(rv)==chickens_used.end()); chickens_used[rv]=1; return rv; } void component_so::allocate_chicken(acomponent* ac) { used_chickens_t::iterator i = chickens_used.find(ac); if(i!=chickens_used.end()) { i->second++; }else{ free_chickens_t::iterator i; for(i=chickens_free.begin();*i!=ac && i!=chickens_free.end();i++); if(i==chickens_free.end()) throw konforka::exception(CODEPOINT,"hens rarely adopt chickens"); chickens_free.erase(i); chickens_used[ac]=1; } } void component_so::deallocate_chicken(acomponent* ac) { used_chickens_t::iterator i = chickens_used.find(ac); if(i==chickens_used.end()) throw konforka::exception(CODEPOINT,"you can't deallocate what is not allocated"); i->second--; if(i->second>0) return; chickens_used.erase(i); chickens_free.push_front(ac); } /* * so_component */ so_component::so_component(component_so *h,sitecing_interface *scif) : hen(h), ac(NULL) { if(!hen) throw konforka::exception(CODEPOINT,"can't get an egg from the null-hen"); ac = hen->allocate_chicken(); ac->__set_interface(scif); } void so_component::attach(component_so *h,acomponent *a) { detach(); hen = h; ac = a; if(!ac) throw konforka::exception(CODEPOINT,"trying to clone null-chicken"); if(!hen) throw konforka::exception(CODEPOINT,"trying to clone orphan chicken"); hen->allocate_chicken(ac); } void so_component::detach() { if(hen && ac) hen->deallocate_chicken(ac); } }