1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#ifdef USE_PCH
#include "pch.h"
#else
#include <unistd.h>
#include <dlfcn.h>
#include <iostream>
#include <cassert>
#include <stdexcept>
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);
}
}
|