Skip to content

Commit 629d45c

Browse files
committed
Return defaultResult when not waiting for callback result
1 parent 2452c40 commit 629d45c

5 files changed

Lines changed: 73 additions & 16 deletions

File tree

generate/templates/manual/include/async_baton.h

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,48 @@
1212
// or field properties of configuration objects whose values are callbacks)
1313
struct AsyncBaton {
1414
uv_sem_t semaphore;
15+
16+
virtual ~AsyncBaton() {}
1517
};
1618

19+
void deleteBaton(AsyncBaton *baton);
20+
1721
template<typename ResultT>
1822
struct AsyncBatonWithResult : public AsyncBaton {
1923
ResultT result;
2024
ResultT defaultResult; // result returned if the callback doesn't return anything valid
25+
void (*onCompletion)(AsyncBaton *);
2126

2227
AsyncBatonWithResult(const ResultT &defaultResult)
2328
: defaultResult(defaultResult) {
24-
uv_sem_init(&semaphore, 0);
25-
}
26-
27-
~AsyncBatonWithResult() {
28-
uv_sem_destroy(&semaphore);
2929
}
3030

3131
void Done() {
32-
// signal completion
33-
uv_sem_post(&semaphore);
32+
if (onCompletion) {
33+
onCompletion(this);
34+
} else {
35+
// signal completion
36+
uv_sem_post(&semaphore);
37+
}
3438
}
3539

36-
ResultT ExecuteAsync(ThreadPool::Callback asyncCallback) {
40+
ResultT ExecuteAsync(ThreadPool::Callback asyncCallback, void (*onCompletion)(AsyncBaton *) = NULL) {
3741
result = 0;
42+
this->onCompletion = onCompletion;
43+
if (!onCompletion) {
44+
uv_sem_init(&semaphore, 0);
45+
}
3846

3947
{
4048
LockMaster::TemporaryUnlock temporaryUnlock;
4149

4250
libgit2ThreadPool.ExecuteReverseCallback(asyncCallback, this);
4351

44-
// wait for completion
45-
uv_sem_wait(&semaphore);
52+
if (!onCompletion) {
53+
// wait for completion
54+
uv_sem_wait(&semaphore);
55+
uv_sem_destroy(&semaphore);
56+
}
4657
}
4758

4859
return result;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#include "../include/async_baton.h"
2+
3+
void deleteBaton(AsyncBaton *baton) {
4+
delete baton;
5+
}

generate/templates/partials/field_accessors.cc

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,19 +119,28 @@
119119
{{ arg.cType }} {{ arg.name}}{% if not arg.lastArg %},{% endif %}
120120
{% endeach %}
121121
) {
122-
{{ field.name|titleCase }}Baton baton({{ field.return.noResults }});
122+
{{ field.name|titleCase }}Baton *baton =
123+
new {{ field.name|titleCase }}Baton({{ field.return.noResults }});
123124

124125
{% each field.args|argsInfo as arg %}
125-
baton.{{ arg.name }} = {{ arg.name }};
126+
baton->{{ arg.name }} = {{ arg.name }};
126127
{% endeach %}
127128

128-
{{ cppClassName }}* instance = {{ field.name }}_getInstanceFromBaton(&baton);
129+
{{ cppClassName }}* instance = {{ field.name }}_getInstanceFromBaton(baton);
130+
131+
{{ field.return.type }} result;
129132

130133
if (instance->{{ field.name }}.WillBeThrottled()) {
131-
return baton.defaultResult;
134+
result = baton->defaultResult;
135+
delete baton;
136+
} else if (instance->{{ field.name }}.ShouldWaitForResult()) {
137+
result = baton->ExecuteAsync({{ field.name }}_async);
138+
delete baton;
139+
} else {
140+
result = baton->defaultResult;
141+
baton->ExecuteAsync({{ field.name }}_async, deleteBaton);
132142
}
133-
134-
return baton.ExecuteAsync({{ field.name }}_async);
143+
return result;
135144
}
136145

137146
void {{ cppClassName }}::{{ field.name }}_async(void *untypedBaton) {

generate/templates/templates/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
},
1313

1414
"sources": [
15+
"src/async_baton.cc",
1516
"src/lock_master.cc",
1617
"src/nodegit.cc",
1718
"src/init_ssh2.cc",

test/tests/clone.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,37 @@ describe("Clone", function() {
166166
});
167167
});
168168

169+
it("can clone without waiting for callback results", function() {
170+
var test = this;
171+
var url = "https://github.com/nodegit/test.git";
172+
var lastReceivedObjects = 0;
173+
var cloneFinished = false;
174+
var opts = {
175+
fetchOpts: {
176+
callbacks: {
177+
transferProgress: {
178+
waitForResult: false,
179+
callback: function(progress) {
180+
var receivedObjects = progress.receivedObjects();
181+
assert.false(
182+
cloneFinished,
183+
"callback running after clone completion"
184+
);
185+
assert.gt(receivedObjects, lastReceivedObjects);
186+
lastReceivedObjects = receivedObjects;
187+
}
188+
}
189+
}
190+
}
191+
};
192+
193+
return Clone(url, clonePath, opts).then(function(repo) {
194+
assert.ok(repo instanceof Repository);
195+
cloneFinished = true;
196+
test.repository = repo;
197+
});
198+
});
199+
169200
it("can clone using nested function", function() {
170201
var test = this;
171202
var url = "https://github.com/nodegit/test.git";

0 commit comments

Comments
 (0)