Project

General

Profile

Download (1.41 KB) Statistics
| Branch: | Tag: | Revision:

haketilo / common / lock.js @ 6b12a034

1
/**
2
 * Hachette lock (aka binary semaphore aka mutex)
3
 *
4
 * Copyright (C) 2021 Wojtek Kosior
5
 * Redistribution terms are gathered in the `copyright' file.
6
 */
7

    
8
/*
9
 * Javascript runs single-threaded, with an event loop. Because of that,
10
 * explicit synchronization is often not needed. An exception is when we use
11
 * an API function that must wait. Ajax is an example. Callback passed to ajax
12
 * call doesn't get called immediately, but after some time. In the meantime
13
 * some other piece of code might get to execute and modify some variables.
14
 * Access to WebExtension local storage is another situation where this problem
15
 * can occur.
16
 *
17
 * This is a solution. A lock object, that can be used to delay execution of
18
 * some code until other code finishes its critical work. Locking is wrapped
19
 * in a promise.
20
 */
21

    
22
function make_lock() {
23
    return {free: true, queue: []};
24
}
25

    
26
function _lock(lock, cb) {
27
    if (lock.free) {
28
	lock.free = false;
29
	setTimeout(cb);
30
    } else {
31
	lock.queue.push(cb);
32
    }
33
}
34

    
35
function lock(lock) {
36
    return new Promise((resolve, reject) => _lock(lock, resolve));
37
}
38

    
39
function unlock(lock) {
40
    if (lock.free)
41
	throw new Exception("Attempting to release a free lock");
42

    
43
    if (lock.queue.length === 0) {
44
	lock.free = true;
45
    } else {
46
	let cb = lock.queue[0];
47
	lock.queue.splice(0, 1);
48
	setTimeout(cb);
49
    }
50
}
51

    
52
/*
53
 * EXPORTS_START
54
 * EXPORT make_lock
55
 * EXPORT lock
56
 * EXPORT unlock
57
 * EXPORTS_END
58
 */
(2-2/8)