2
* Copyright 2016 Software Freedom Conservancy Inc.
4
* This software is licensed under the GNU Lesser General Public License
5
* (version 2.1 or later). See the COPYING file in this distribution.
8
private class Geary.Db.TransactionAsyncJob : BaseObject {
10
internal Connection? cx { get; private set; default = null; }
11
internal Cancellable cancellable { get; private set; }
13
private TransactionType type;
14
private unowned TransactionMethod cb;
15
private Nonblocking.Event completed;
16
private TransactionOutcome outcome = TransactionOutcome.ROLLBACK;
17
private Error? caught_err = null;
20
public TransactionAsyncJob(Connection? cx,
23
Cancellable? cancellable) {
27
this.cancellable = cancellable ?? new Cancellable();
29
this.completed = new Nonblocking.Event();
32
public bool is_cancelled() {
33
return cancellable.is_cancelled();
36
// Called in background thread context
37
internal void execute(Connection cx) {
38
// execute transaction
40
// possible was cancelled during interim of scheduling and execution
42
throw new IOError.CANCELLED("Async transaction cancelled");
44
outcome = cx.exec_transaction(type, cb, cancellable);
46
if (!(err is IOError.CANCELLED))
47
debug("AsyncJob: transaction completed with error: %s", err.message);
52
schedule_completion();
55
// Called in background thread context
56
internal void failed(Error err) {
57
// store as a caught thread to report to original caller
60
schedule_completion();
63
private void schedule_completion() {
64
// notify foreground thread of completion
65
// because Idle doesn't hold a ref, manually keep this object alive
68
// NonblockingSemaphore and its brethren are not thread-safe, so need to signal notification
69
// of completion in the main thread
70
Idle.add(on_notify_completed);
73
private bool on_notify_completed() {
77
if (caught_err != null && !(caught_err is IOError.CANCELLED)) {
78
debug("Unable to notify AsyncTransaction has completed w/ err %s: %s",
79
caught_err.message, err.message);
81
debug("Unable to notify AsyncTransaction has completed w/o err: %s", err.message);
85
// manually unref; do NOT touch "this" once unref() returns, as this object may be freed
91
// No way to cancel this because the callback thread *must* finish before
92
// we move on here. Any I/O the thread is doing can still be cancelled
93
// using the job's cancellable.
94
public async TransactionOutcome wait_for_completion_async()
96
yield this.completed.wait_async();
97
if (this.caught_err != null)
98
throw this.caught_err;