-rw-r--r-- | lib/component_so.cc | 112 |
1 files changed, 112 insertions, 0 deletions
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 @@ | |||
1 | #ifdef USE_PCH | ||
2 | #include "pch.h" | ||
3 | #else | ||
4 | #include <unistd.h> | ||
5 | #include <dlfcn.h> | ||
6 | #include <iostream> | ||
7 | #include <cassert> | ||
8 | #include <stdexcept> | ||
9 | using namespace std; | ||
10 | #include "sitecing/component_so.h" | ||
11 | #include "sitecing/sitecing_util.h" | ||
12 | #endif | ||
13 | |||
14 | namespace sitecing { | ||
15 | |||
16 | /* | ||
17 | * component_so | ||
18 | */ | ||
19 | |||
20 | component_so::component_so(const string& soname) | ||
21 | : dl(NULL), sofile(soname) { | ||
22 | if(stat(sofile.c_str(),&stso)) | ||
23 | throw konforka::exception(CODEPOINT,"failed to stat() shared object"); | ||
24 | file_lock lock(sofile+".lock"); | ||
25 | dl = dlopen(sofile.c_str(),RTLD_LAZY); | ||
26 | lock.unlock(); | ||
27 | if(!dl) | ||
28 | throw konforka::exception(CODEPOINT,"failed to dlopen: "+string(dlerror())); | ||
29 | egg = (egg_t)dlsym(dl,"_egg"); | ||
30 | if(!egg) | ||
31 | throw konforka::exception(CODEPOINT,"failed to dlsym: "+string(dlerror())); | ||
32 | } | ||
33 | component_so::~component_so() { | ||
34 | for(free_chickens_t::iterator i=chickens_free.begin();i!=chickens_free.end();i++) | ||
35 | delete *i; | ||
36 | chickens_free.clear(); | ||
37 | if(!chickens_used.empty()) | ||
38 | throw konforka::exception(CODEPOINT,"attempt to destroy the component in use"); | ||
39 | dlclose(dl); | ||
40 | } | ||
41 | |||
42 | bool component_so::is_uptodate() const { | ||
43 | struct stat st; | ||
44 | if(stat(sofile.c_str(),&st)) | ||
45 | throw konforka::exception(CODEPOINT,"failed to stat() shared object"); | ||
46 | return stso.st_mtime==st.st_mtime; | ||
47 | } | ||
48 | |||
49 | acomponent* component_so::allocate_chicken() { | ||
50 | acomponent *rv; | ||
51 | if(!chickens_free.empty()) { | ||
52 | rv = chickens_free.front(); | ||
53 | chickens_free.pop_front(); | ||
54 | }else{ | ||
55 | rv = (*egg)(); | ||
56 | } | ||
57 | assert(chickens_used.find(rv)==chickens_used.end()); | ||
58 | chickens_used[rv]=1; | ||
59 | return rv; | ||
60 | } | ||
61 | |||
62 | void component_so::allocate_chicken(acomponent* ac) { | ||
63 | used_chickens_t::iterator i = chickens_used.find(ac); | ||
64 | if(i!=chickens_used.end()) { | ||
65 | i->second++; | ||
66 | }else{ | ||
67 | free_chickens_t::iterator i; | ||
68 | for(i=chickens_free.begin();*i!=ac && i!=chickens_free.end();i++); | ||
69 | if(i==chickens_free.end()) | ||
70 | throw konforka::exception(CODEPOINT,"hens rarely adopt chickens"); | ||
71 | chickens_free.erase(i); | ||
72 | chickens_used[ac]=1; | ||
73 | } | ||
74 | } | ||
75 | |||
76 | void component_so::deallocate_chicken(acomponent* ac) { | ||
77 | used_chickens_t::iterator i = chickens_used.find(ac); | ||
78 | if(i==chickens_used.end()) | ||
79 | throw konforka::exception(CODEPOINT,"you can't deallocate what is not allocated"); | ||
80 | i->second--; | ||
81 | if(i->second>0) | ||
82 | return; | ||
83 | chickens_used.erase(i); | ||
84 | chickens_free.push_front(ac); | ||
85 | } | ||
86 | |||
87 | /* | ||
88 | * so_component | ||
89 | */ | ||
90 | |||
91 | so_component::so_component(component_so *h,sitecing_interface *scif) | ||
92 | : hen(h), ac(NULL) { | ||
93 | if(!hen) | ||
94 | throw konforka::exception(CODEPOINT,"can't get an egg from the null-hen"); | ||
95 | ac = hen->allocate_chicken(); | ||
96 | ac->__set_interface(scif); | ||
97 | } | ||
98 | |||
99 | void so_component::attach(component_so *h,acomponent *a) { | ||
100 | detach(); hen = h; ac = a; | ||
101 | if(!ac) | ||
102 | throw konforka::exception(CODEPOINT,"trying to clone null-chicken"); | ||
103 | if(!hen) | ||
104 | throw konforka::exception(CODEPOINT,"trying to clone orphan chicken"); | ||
105 | hen->allocate_chicken(ac); | ||
106 | } | ||
107 | void so_component::detach() { | ||
108 | if(hen && ac) | ||
109 | hen->deallocate_chicken(ac); | ||
110 | } | ||
111 | |||
112 | } | ||