-
Notifications
You must be signed in to change notification settings - Fork 6
/
handle.cc
109 lines (100 loc) · 2.18 KB
/
handle.cc
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
#include "handle.h"
#include <stdio.h>
#include "tprintf.h"
handle_mgr mgr;
handle::handle(std::string m)
{
h = mgr.get_handle(m);
}
rpcc *
handle::safebind()
{
if (!h)
return NULL;
ScopedLock ml(&h->cl_mutex);
if (h->del)
return NULL;
if (h->cl)
return h->cl;
sockaddr_in dstsock;
make_sockaddr(h->m.c_str(), &dstsock);
rpcc *cl = new rpcc(dstsock);
tprintf("handler_mgr::get_handle trying to bind...%s\n", h->m.c_str());
int ret;
// handle class has to tolerate lossy network, since we may test
// students' lab with RPC_LOSSY=5 from lab 1 to lab 5
ret = cl->bind();
if (ret < 0) {
tprintf("handle_mgr::get_handle bind failure! %s %d\n", h->m.c_str(), ret);
delete cl;
h->del = true;
} else {
tprintf("handle_mgr::get_handle bind succeeded %s\n", h->m.c_str());
h->cl = cl;
}
return h->cl;
}
handle::~handle()
{
if (h) mgr.done_handle(h);
}
handle_mgr::handle_mgr()
{
VERIFY (pthread_mutex_init(&handle_mutex, NULL) == 0);
}
struct hinfo *
handle_mgr::get_handle(std::string m)
{
ScopedLock ml(&handle_mutex);
struct hinfo *h = 0;
if (hmap.find(m) == hmap.end()) {
h = new hinfo;
h->cl = NULL;
h->del = false;
h->refcnt = 1;
h->m = m;
pthread_mutex_init(&h->cl_mutex, NULL);
hmap[m] = h;
} else if (!hmap[m]->del) {
h = hmap[m];
h->refcnt ++;
}
return h;
}
void
handle_mgr::done_handle(struct hinfo *h)
{
ScopedLock ml(&handle_mutex);
h->refcnt--;
if (h->refcnt == 0 && h->del)
delete_handle_wo(h->m);
}
void
handle_mgr::delete_handle(std::string m)
{
ScopedLock ml(&handle_mutex);
delete_handle_wo(m);
}
// Must be called with handle_mutex locked.
void
handle_mgr::delete_handle_wo(std::string m)
{
if (hmap.find(m) == hmap.end()) {
tprintf("handle_mgr::delete_handle_wo: cl %s isn't in cl list\n", m.c_str());
} else {
tprintf("handle_mgr::delete_handle_wo: cl %s refcnt %d\n", m.c_str(),
hmap[m]->refcnt);
struct hinfo *h = hmap[m];
if (h->refcnt == 0) {
if (h->cl) {
h->cl->cancel();
delete h->cl;
}
pthread_mutex_destroy(&h->cl_mutex);
hmap.erase(m);
delete h;
} else {
h->del = true;
}
}
}