vlc_executor.h 5.8 KB
Newer Older
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*****************************************************************************
 * vlc_executor.h
 *****************************************************************************
 * Copyright (C) 2020 Videolabs, VLC authors and VideoLAN
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#ifndef VLC_EXECUTOR_H
#define VLC_EXECUTOR_H

#include <vlc_common.h>
#include <vlc_tick.h>

# ifdef __cplusplus
extern "C" {
# endif

/** Executor type (opaque) */
typedef struct vlc_executor vlc_executor_t;

/**
 * A Runnable is intended to be run from another thread by an executor.
 */
struct vlc_runnable {

    /**
     * This function is to be executed by a vlc_executor_t.
     *
     * It must implement the actions (arbitrarily long) to execute from an
     * executor thread, synchronously. As soon as run() returns, the execution
     * of this runnable is complete.
     *
     * After the runnable is submitted to an executor via
     * vlc_executor_Submit(), the run() function is executed at most once (zero
     * if the execution is canceled before it was started).
     *
     * It may not be NULL.
     *
     * \param userdata the userdata provided to vlc_executor_Submit()
     */
    void (*run)(void *userdata);

    /**
     * This function attempts to interrupt the execution of run().
     *
     * If not NULL, it may be called on vlc_executor_Cancel() or on timeout.
     *
     * It is called from a thread different from the one executing run(). It is
     * free to do any actions to "interrupt" the execution of run() (set a
     * flag, close a file descriptor, etc.).
     *
     * The runnable will be considered "finished" once run() actually
     * terminates.
     *
     * It should be quick, not to block the interruption of other runnables.
     *
     * \param userdata the userdata provided to vlc_executor_Submit()
     */
    void (*interrupt)(void *userdata);

    /**
     * This function notifies the end of the execution.
     *
     * If not NULL, it is called either:
     *  - when run() terminates;
     *  - when the task is canceled before run() is called.
     *
     * In other words, it is always called in the end if vlc_executor_Submit()
     * returns VLC_SUCCESS.
     *
     * \param userdata the userdata provided to vlc_executor_Submit()
     */
    void (*on_finished)(void *userdata);
};

/**
 * Create a new executor.
 *
 * \param max_threads the maximum number of threads used to execute runnables
 * \return a pointer to a new executor, or NULL if an error occurred
 */
VLC_API vlc_executor_t *
vlc_executor_New(unsigned max_threads);

/**
 * Delete an executor.
 *
 * Cancel all the tasks, wait for all the threads to complete, and delete the
 * executor instance.
 *
 * \param executor the executor
 */
VLC_API void
vlc_executor_Delete(vlc_executor_t *executor);

/**
 * Submit a runnable for execution.
 *
 * The struct vlc_runnable is not copied, it must exist until the end of the
 * execution (the user is expected to pass a pointer to a static const
 * structure).
 *
 * An id may optionally be provided in order to explicitly cancel the task
 * later with vlc_executor_Cancel().
 *
 * A timeout may optionally be provided to interrupt the execution after some
 * delay. The way the interruption is actually handled must be provided by the
 * user via the runnable callback "interrupt". It is an error to provide a
 * timeout without an interrupt callback.
 *
 * Here is a simple example (without interruption):
 *
 * \code{c}
 *  static void Run(void *userdata)
 *  {
 *      char *str = userdata;
 *      printf("start of %s\n", str);
 *      vlc_tick_sleep(VLC_TICK_FROM_SEC(3));
 *      printf("end of %s\n", str);
 *  }
 *
 *  static void OnFinished(void *userdata)
 *  {
 *      free(userdata);
 *  }
 *
 *  static const struct vlc_runnable runnable = {
 *      .run = Run,
 *      .on_finished = OnFinished,
 *  };
 *
 *  void foo(vlc_executor_t *executor, const char *name)
 *  {
 *      // error handling replaced by assertions for brevity
 *      char *str = strdup(name);
 *      assert(str);
 *      int ret = vlc_executor_Submit(executor, &runnable, str, NULL, 0);
 *      assert(ret == VLC_SUCCESS);
 *  }
 * \endcode
 *
 * \param executor the executor
 * \param runnable the task to run
 * \param userdata the userdata to pass to all runnable callbacks
 * \param id       a user-provided id to associate to the task, used to cancel
 *                 the execution (may be NULL)
 * \param timeout  the delay before the task is automatically interrupted
 *                 (0 for no timeout, negative values are illegal)
 * \return VLC_SUCCESS on success, another value on error
 */
VLC_API int
vlc_executor_Submit(vlc_executor_t *executor,
                    const struct vlc_runnable *runnable, void *userdata,
                    void *id, vlc_tick_t timeout);

/**
 * Cancel all submitted tasks having the specified id.
 *
 * If id is NULL, then cancel all tasks.
 *
 * \param executor the executor
 * \param id       the id of the tasks to cancel (NULL for all tasks)
 */
VLC_API void
vlc_executor_Cancel(vlc_executor_t *executor, void *id);

# ifdef __cplusplus
}
# endif

 #endif