summaryrefslogtreecommitdiffabout
path: root/lib/component_so.cc
Unidiff
Diffstat (limited to 'lib/component_so.cc') (more/less context) (ignore whitespace changes)
-rw-r--r--lib/component_so.cc112
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
14namespace 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}