Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 12 additions & 15 deletions 27 generate/templates/manual/src/lock_master.cc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <nan.h>
#include <git2.h>
#include <uv.h>
#include <set>
Expand Down Expand Up @@ -31,10 +32,8 @@ class LockMasterImpl {
// A libuv key used to store the current thread-specific LockMasterImpl instance
static uv_key_t currentLockMasterKey;

// A libuv async handle used to trigger / debounce mutex cleanup
static uv_async_t cleanupMutexesHandle;
// Cleans up any mutexes that are not currently used
static void CleanupMutexes(uv_async_t *async);
static NAN_GC_CALLBACK(CleanupMutexes);

public:
static void Initialize();
Expand All @@ -49,7 +48,6 @@ class LockMasterImpl {
std::vector<uv_mutex_t *> GetMutexes(int useCountDelta);
void Register();
void Unregister();
void CleanupMutexes();

public:
static LockMasterImpl *CurrentLockMasterImpl() {
Expand All @@ -64,7 +62,6 @@ class LockMasterImpl {
~LockMasterImpl() {
Unregister();
Unlock(true);
CleanupMutexes();
}

void ObjectToLock(const void *objectToLock) {
Expand All @@ -78,16 +75,22 @@ class LockMasterImpl {
std::map<const void *, ObjectInfo> LockMasterImpl::mutexes;
uv_mutex_t LockMasterImpl::mapMutex;
uv_key_t LockMasterImpl::currentLockMasterKey;
uv_async_t LockMasterImpl::cleanupMutexesHandle;


void LockMasterImpl::Initialize() {
uv_mutex_init(&mapMutex);
uv_key_create(&currentLockMasterKey);
uv_async_init(uv_default_loop(), &cleanupMutexesHandle, CleanupMutexes);
Nan::AddGCEpilogueCallback(CleanupMutexes);
}

void LockMasterImpl::CleanupMutexes(uv_async_t *async) {
NAN_GC_CALLBACK(LockMasterImpl::CleanupMutexes) {
// skip cleanup if thread safety is disabled
// this means that turning thread safety on and then off
// could result in remaining mutexes - but they would get cleaned up
// if thread safety is turned on again
if (!LockMaster::IsEnabled()) {
return;
}

uv_mutex_lock(&mapMutex);

for (auto it = mutexes.begin(); it != mutexes.end(); )
Expand Down Expand Up @@ -197,12 +200,6 @@ void LockMasterImpl::Unlock(bool releaseMutexes) {
GetMutexes(releaseMutexes * -1);
}

void LockMasterImpl::CleanupMutexes() {
// schedule mutex cleanup on the main event loop
// this somewhat delays and debounces cleanup (uv_async_send coalesces calls)
uv_async_send(&cleanupMutexesHandle);
}

LockMaster::Diagnostics LockMasterImpl::GetDiagnostics() {
LockMaster::Diagnostics diagnostics;
uv_mutex_lock(&LockMasterImpl::mapMutex);
Expand Down
11 changes: 7 additions & 4 deletions 11 test/tests/thread_safety.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,18 +42,21 @@ describe("ThreadSafety", function() {
}
});

it("can lock something", function() {
it("can lock something and cleanup mutex", function() {
// call a sync method to guarantee that it stores a mutex,
// and that it will not clean up the mutex (since the cleanup is
// scheduled on the main node thread)
// and that it will clean up the mutex in a garbage collection cycle
this.repository.headDetached();

var diagnostics = NodeGit.getThreadSafetyDiagnostics();
if (diagnostics.isEnabled) {
if (NodeGit.isThreadSafetyEnabled()) {
// this is a fairly vague test - it just tests that something
// had a mutex created for it at some point (i.e., the thread safety
// code is not completely dead)
assert.ok(diagnostics.storedMutexesCount > 0);
// now test that GC cleans up mutexes
global.gc();
diagnostics = NodeGit.getThreadSafetyDiagnostics();
assert.equal(0, diagnostics.storedMutexesCount);
} else {
assert.equal(0, diagnostics.storedMutexesCount);
}
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.