Project

General

Profile

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

haketilo / common / lock.js @ b93f26bf

1
/**
2
 * Myext 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
"use strict";
23

    
24
(() => {
25
    function make_lock() {
26
	return {free: true, queue: []};
27
    }
28

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

    
38
    function lock(lock) {
39
	return new Promise((resolve, reject) => _lock(lock, resolve));
40
    }
41

    
42
    function unlock(lock) {
43
	if (lock.free)
44
	    throw new Exception("Attempting to release a free lock");
45

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

    
55
    window.make_lock = make_lock;
56
    window.lock = lock;
57
    window.unlock = unlock;
58
})();
(4-4/9)