/
gitobjectwrap_new.h
129 lines (102 loc) · 2.6 KB
/
gitobjectwrap_new.h
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#ifndef GITTEH_WRAPPED_GIT_OBJECT_H
#define GITTEH_WRAPPED_GIT_OBJECT_H
#include "gitteh.h"
#include "object_cache.h"
#include <errno.h>
namespace gitteh {
template<class T, class S>
class WrappedGitObject : public ObjectWrap {
public:
WrappedGitObject() {
CREATE_MUTEX(gatekeeperLock_);
initialized_ = false;
initializing_ = false;
initInterest_ = 0;
initResult_ = GIT_ERROR;
}
~WrappedGitObject() {
DESTROY_MUTEX(gatekeeperLock_);
}
inline void setCache(WrappedGitObjectCache<T, S> *cache) {
cache_ = cache;
}
bool isInitialized() {
LOCK_MUTEX(gatekeeperLock_);
bool isInitialized = initialized_;
UNLOCK_MUTEX(gatekeeperLock_);
return isInitialized;
}
inline void registerInitInterest() {
LOCK_MUTEX(gatekeeperLock_);
initInterest_++;
UNLOCK_MUTEX(gatekeeperLock_);
}
inline int initialize(S *gitObj) {
LOCK_MUTEX(gatekeeperLock_);
/*if(initialized_) {
UNLOCK_MUTEX(gatekeeperLock_);
return initResult_;
}*/
bool shouldInitialize = !initializing_;
if(shouldInitialize) {
initializing_ = true;
CREATE_MUTEX(initLock_);
LOCK_MUTEX(initLock_);
}
UNLOCK_MUTEX(gatekeeperLock_);
if(shouldInitialize) {
initResult_ = doInit();
if(initResult_ != GIT_OK) {
cache_->remove(gitObj);
}
LOCK_MUTEX(gatekeeperLock_);
initialized_ = true;
UNLOCK_MUTEX(gatekeeperLock_);
UNLOCK_MUTEX(initLock_);
}
else {
while(pthread_mutex_trylock(&initLock_) == EBUSY) {
usleep(1000);
}
UNLOCK_MUTEX(initLock_);
}
LOCK_MUTEX(gatekeeperLock_);
bool killInitLock = !(--initInterest_);
UNLOCK_MUTEX(gatekeeperLock_);
if(killInitLock) {
if(initResult_ != GIT_OK) {
// We're the last one out the door on a botched initialization
// attempt.
delete this;
}
DESTROY_MUTEX(initLock_);
}
return initResult_;
}
// Ensure this object is wrapped in a JS object.
inline void ensureWrapped() {
HandleScope scope;
if(handle_.IsEmpty()) {
Handle<Value> constructorArgs[1] = { External::New(this) };
T::constructor_template->GetFunction()->NewInstance(1, constructorArgs);
cache_->objectWrapped((T*)this);
}
cache_->unrefWrapped((T*)this);
}
inline void dontDieOnMeNow() {
Ref();
Unref();
}
protected:
virtual int doInit() = 0;
private:
gitteh_lock gatekeeperLock_;
gitteh_lock initLock_;
bool initialized_;
bool initializing_;
int initResult_;
int initInterest_;
WrappedGitObjectCache<T, S> *cache_;
};
} // namespace gitteh
#endif // GITTEH_WRAPPED_GIT_OBJECT_H