Skip to content

Commit ed068ad

Browse files
committed
Make LockMaster shareable across contexts
1 parent 5cafd47 commit ed068ad

File tree

5 files changed

+28
-191
lines changed

5 files changed

+28
-191
lines changed

generate/templates/manual/include/lock_master.h

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,7 @@
66
class LockMasterImpl;
77

88
class LockMaster {
9-
public:
10-
enum Status {
11-
Disabled = 0,
12-
EnabledForAsyncOnly,
13-
Enabled
14-
};
15-
169
private:
17-
static Status status;
18-
1910
LockMasterImpl *impl;
2011

2112
template<typename T>
@@ -44,7 +35,7 @@ class LockMaster {
4435

4536
// we lock on construction
4637
template<typename ...Types> LockMaster(bool asyncAction, const Types*... types) {
47-
if((status == Disabled) || ((status == EnabledForAsyncOnly) && !asyncAction)) {
38+
if(!asyncAction) {
4839
impl = NULL;
4940
return;
5041
}
@@ -85,33 +76,8 @@ class LockMaster {
8576
}
8677
};
8778

88-
static void Initialize();
89-
90-
// Enables the thread safety system
91-
static void Enable() {
92-
status = Enabled;
93-
}
94-
95-
static void SetStatus(Status status) {
96-
LockMaster::status = status;
97-
}
98-
99-
static void Disable() {
100-
status = Disabled;
101-
}
102-
103-
static Status GetStatus() {
104-
return status;
105-
}
106-
107-
// Diagnostic information that can be provided to the JavaScript layer
108-
// for a minimal level of testing
109-
struct Diagnostics {
110-
// this counts all stored mutexes - even if they are unlocked:
111-
int storedMutexesCount;
112-
};
113-
114-
static Diagnostics GetDiagnostics();
79+
static void InitializeGlobal();
80+
static void InitializeContext();
11581
};
11682

11783

generate/templates/manual/src/lock_master.cc

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ class LockMasterImpl {
3636
static NAN_GC_CALLBACK(CleanupMutexes);
3737

3838
public:
39-
static void Initialize();
39+
static void InitializeGlobal();
40+
41+
static void InitializeContext();
4042

4143
// INSTANCE variables / methods
4244

@@ -53,7 +55,6 @@ class LockMasterImpl {
5355
static LockMasterImpl *CurrentLockMasterImpl() {
5456
return (LockMasterImpl *)uv_key_get(&currentLockMasterKey);
5557
}
56-
static LockMaster::Diagnostics GetDiagnostics();
5758

5859
LockMasterImpl() {
5960
Register();
@@ -76,21 +77,16 @@ std::map<const void *, ObjectInfo> LockMasterImpl::mutexes;
7677
uv_mutex_t LockMasterImpl::mapMutex;
7778
uv_key_t LockMasterImpl::currentLockMasterKey;
7879

79-
void LockMasterImpl::Initialize() {
80+
void LockMasterImpl::InitializeGlobal() {
8081
uv_mutex_init(&mapMutex);
8182
uv_key_create(&currentLockMasterKey);
83+
}
84+
85+
void LockMasterImpl::InitializeContext() {
8286
Nan::AddGCEpilogueCallback(CleanupMutexes);
8387
}
8488

8589
NAN_GC_CALLBACK(LockMasterImpl::CleanupMutexes) {
86-
// skip cleanup if thread safety is disabled
87-
// this means that turning thread safety on and then off
88-
// could result in remaining mutexes - but they would get cleaned up
89-
// if thread safety is turned on again
90-
if (LockMaster::GetStatus() == LockMaster::Disabled) {
91-
return;
92-
}
93-
9490
uv_mutex_lock(&mapMutex);
9591

9692
for (auto it = mutexes.begin(); it != mutexes.end(); )
@@ -113,8 +109,12 @@ NAN_GC_CALLBACK(LockMasterImpl::CleanupMutexes) {
113109
uv_mutex_unlock(&mapMutex);
114110
}
115111

116-
void LockMaster::Initialize() {
117-
LockMasterImpl::Initialize();
112+
void LockMaster::InitializeGlobal() {
113+
LockMasterImpl::InitializeGlobal();
114+
}
115+
116+
void LockMaster::InitializeContext() {
117+
LockMasterImpl::InitializeContext();
118118
}
119119

120120
std::vector<uv_mutex_t *> LockMasterImpl::GetMutexes(int useCountDelta) {
@@ -200,14 +200,6 @@ void LockMasterImpl::Unlock(bool releaseMutexes) {
200200
GetMutexes(releaseMutexes * -1);
201201
}
202202

203-
LockMaster::Diagnostics LockMasterImpl::GetDiagnostics() {
204-
LockMaster::Diagnostics diagnostics;
205-
uv_mutex_lock(&LockMasterImpl::mapMutex);
206-
diagnostics.storedMutexesCount = mutexes.size();
207-
uv_mutex_unlock(&LockMasterImpl::mapMutex);
208-
return diagnostics;
209-
}
210-
211203
// LockMaster
212204

213205
void LockMaster::ConstructorImpl() {
@@ -226,10 +218,6 @@ void LockMaster::ObjectsToLockAdded() {
226218
impl->Lock(true);
227219
}
228220

229-
LockMaster::Diagnostics LockMaster::GetDiagnostics() {
230-
return LockMasterImpl::GetDiagnostics();
231-
}
232-
233221
// LockMaster::TemporaryUnlock
234222

235223
void LockMaster::TemporaryUnlock::ConstructorImpl() {
@@ -242,5 +230,3 @@ void LockMaster::TemporaryUnlock::ConstructorImpl() {
242230
void LockMaster::TemporaryUnlock::DestructorImpl() {
243231
impl->Lock(false);
244232
}
245-
246-
LockMaster::Status LockMaster::status = LockMaster::Disabled;

generate/templates/templates/nodegit.cc

Lines changed: 12 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -23,56 +23,24 @@
2323
#include "../include/convenient_hunk.h"
2424
#include "../include/filter_registry.h"
2525

26-
v8::Local<v8::Value> GetPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key) {
27-
v8::Local<v8::Value> value;
26+
using namespace v8;
27+
28+
Local<Value> GetPrivate(Local<Object> object, Local<String> key) {
29+
Local<Value> value;
2830
Nan::Maybe<bool> result = Nan::HasPrivate(object, key);
2931
if (!(result.IsJust() && result.FromJust()))
30-
return v8::Local<v8::Value>();
32+
return Local<Value>();
3133
if (Nan::GetPrivate(object, key).ToLocal(&value))
3234
return value;
33-
return v8::Local<v8::Value>();
35+
return Local<Value>();
3436
}
3537

36-
void SetPrivate(v8::Local<v8::Object> object, v8::Local<v8::String> key, v8::Local<v8::Value> value) {
38+
void SetPrivate(Local<Object> object, Local<String> key, Local<Value> value) {
3739
if (value.IsEmpty())
3840
return;
3941
Nan::SetPrivate(object, key, value);
4042
}
4143

42-
void LockMasterEnable(const FunctionCallbackInfo<Value>& info) {
43-
LockMaster::Enable();
44-
}
45-
46-
void LockMasterSetStatus(const FunctionCallbackInfo<Value>& info) {
47-
Nan::HandleScope scope;
48-
49-
// convert the first argument to Status
50-
if(info.Length() >= 0 && info[0]->IsNumber()) {
51-
v8::Local<v8::Int32> value = Nan::To<v8::Int32>(info[0]).ToLocalChecked();
52-
LockMaster::Status status = static_cast<LockMaster::Status>(value->Value());
53-
if(status >= LockMaster::Disabled && status <= LockMaster::Enabled) {
54-
LockMaster::SetStatus(status);
55-
return;
56-
}
57-
}
58-
59-
// argument error
60-
Nan::ThrowError("Argument must be one 0, 1 or 2");
61-
}
62-
63-
void LockMasterGetStatus(const FunctionCallbackInfo<Value>& info) {
64-
info.GetReturnValue().Set(Nan::New(LockMaster::GetStatus()));
65-
}
66-
67-
void LockMasterGetDiagnostics(const FunctionCallbackInfo<Value>& info) {
68-
LockMaster::Diagnostics diagnostics(LockMaster::GetDiagnostics());
69-
70-
// return a plain JS object with properties
71-
v8::Local<v8::Object> result = Nan::New<v8::Object>();
72-
Nan::Set(result, Nan::New("storedMutexesCount").ToLocalChecked(), Nan::New(diagnostics.storedMutexesCount));
73-
info.GetReturnValue().Set(result);
74-
}
75-
7644
static uv_mutex_t *opensslMutexes;
7745

7846
void OpenSSL_LockingCallback(int mode, int type, const char *, int) {
@@ -101,8 +69,8 @@ void OpenSSL_ThreadSetup() {
10169
// TODO initialize a thread pool per context. Replace uv_default_loop() with node::GetCurrentEventLoop(isolate);
10270
ThreadPool libgit2ThreadPool(10, uv_default_loop());
10371

104-
std::once_flag libraryInitializedFlag;
105-
std::mutex libraryInitializationMutex;
72+
static std::once_flag libraryInitializedFlag;
73+
static std::mutex libraryInitializationMutex;
10674

10775
NAN_MODULE_INIT(init) {
10876
{
@@ -116,6 +84,8 @@ NAN_MODULE_INIT(init) {
11684
init_ssh2();
11785
// Initialize libgit2.
11886
git_libgit2_init();
87+
88+
LockMaster::InitializeGlobal();
11989
});
12090
}
12191

@@ -133,19 +103,7 @@ NAN_MODULE_INIT(init) {
133103
ConvenientPatch::InitializeComponent(target);
134104
GitFilterRegistry::InitializeComponent(target);
135105

136-
NODE_SET_METHOD(target, "enableThreadSafety", LockMasterEnable);
137-
NODE_SET_METHOD(target, "setThreadSafetyStatus", LockMasterSetStatus);
138-
NODE_SET_METHOD(target, "getThreadSafetyStatus", LockMasterGetStatus);
139-
NODE_SET_METHOD(target, "getThreadSafetyDiagnostics", LockMasterGetDiagnostics);
140-
141-
v8::Local<v8::Object> threadSafety = Nan::New<v8::Object>();
142-
Nan::Set(threadSafety, Nan::New("DISABLED").ToLocalChecked(), Nan::New((int)LockMaster::Disabled));
143-
Nan::Set(threadSafety, Nan::New("ENABLED_FOR_ASYNC_ONLY").ToLocalChecked(), Nan::New((int)LockMaster::EnabledForAsyncOnly));
144-
Nan::Set(threadSafety, Nan::New("ENABLED").ToLocalChecked(), Nan::New((int)LockMaster::Enabled));
145-
146-
Nan::Set(target, Nan::New("THREAD_SAFETY").ToLocalChecked(), threadSafety);
147-
148-
LockMaster::Initialize();
106+
LockMaster::InitializeContext();
149107
}
150108

151109
NODE_MODULE(nodegit, init)

test/runner.js

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,6 @@ var exec = require('../utils/execPromise');
55

66
var NodeGit = require('..');
77

8-
if(process.env.NODEGIT_TEST_THREADSAFETY) {
9-
console.log('Enabling thread safety in NodeGit');
10-
NodeGit.enableThreadSafety();
11-
} else if (process.env.NODEGIT_TEST_THREADSAFETY_ASYNC) {
12-
console.log('Enabling thread safety for async actions only in NodeGit');
13-
NodeGit.setThreadSafetyStatus(NodeGit.THREAD_SAFETY.ENABLED_FOR_ASYNC_ONLY);
14-
}
15-
168
var workdirPath = local("repos/workdir");
179

1810
before(function() {

test/tests/thread_safety.js

Lines changed: 0 additions & 65 deletions
This file was deleted.

0 commit comments

Comments
 (0)