From ce1f37aae46ea95020d7b865f7a80e8abdfad0d8 Mon Sep 17 00:00:00 2001 From: Michael Krelin Date: Sat, 29 Jan 2005 21:21:05 +0000 Subject: initial commit into repository --- (limited to 'lib/component_so.cc') diff --git a/lib/component_so.cc b/lib/component_so.cc new file mode 100644 index 0000000..57cce01 --- a/dev/null +++ b/lib/component_so.cc @@ -0,0 +1,112 @@ +#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); + } + +} -- cgit v0.9.0.2