aboutsummaryrefslogtreecommitdiff
path: root/src/common/detached_tasks.h
blob: 5dd8fc27b0115b68846ac25d95ad7d60a9fc603f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Copyright 2018 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.

#pragma once

#include <condition_variable>
#include <functional>

namespace Common {

/**
 * A background manager which ensures that all detached task is finished before program exits.
 *
 * Some tasks, telemetry submission for example, prefer executing asynchronously and don't care
 * about the result. These tasks are suitable for std::thread::detach(). However, this is unsafe if
 * the task is launched just before the program exits (which is a common case for telemetry), so we
 * need to block on these tasks on program exit.
 *
 * To make detached task safe, a single DetachedTasks object should be placed in the main(), and
 * call WaitForAllTasks() after all program execution but before global/static variable destruction.
 * Any potentially unsafe detached task should be executed via DetachedTasks::AddTask.
 */
class DetachedTasks {
public:
    DetachedTasks();
    ~DetachedTasks();
    void WaitForAllTasks();

    static void AddTask(std::function<void()> task);

private:
    static DetachedTasks* instance;

    std::condition_variable cv;
    std::mutex mutex;
    int count = 0;
};

} // namespace Common