ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/libpeak-0.1.2/peak/task.h
Revision: 3251
Committed: Wed Apr 2 16:58:30 2014 UTC (12 years, 3 months ago) by michael
Content type: text/x-chdr
File size: 14263 byte(s)
Log Message:
- Imported libpeak-0.1.2

File Contents

# User Rev Content
1 michael 3251 /* PEAK Library
2     *
3     * Copyright (c) 2003, 2004
4     * Stephane Thiell <mbuna@bugged.org>. All rights reserved.
5     *
6     * Redistribution and use in source and binary forms, with or without
7     * modification, are permitted provided that the following conditions
8     * are met:
9     *
10     * 1. Redistributions of source code must retain the above copyright
11     * notice, this list of conditions and the following disclaimer.
12     *
13     * 2. Redistributions in binary form must reproduce the above copyright
14     * notice, this list of conditions and the following disclaimer in the
15     * documentation and/or other materials provided with the distribution.
16     *
17     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18     * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19     * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27     * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28     *
29     * $Id: task.h,v 1.3 2004/01/10 14:33:26 mbuna Exp $
30     */
31     #ifndef INCLUDED_PEAK_TASK_H_
32     #define INCLUDED_PEAK_TASK_H_
33    
34     /*!
35     * @defgroup task Task
36     *
37     * In the PEAK library, a task is an abstract object that is eventually
38     * made of several threads to process asynchronous events... It's a bit like
39     * a micro process. Then when you schedule a task for a stream for example,
40     * it will takes the advantage (or the disadvantage) of having several
41     * threads available to process events.
42     */
43     /*!
44     * @ingroup task
45     * @defgroup task_common Task common
46     *
47     * Task common stuffs.
48     */
49     /*!
50     * @ingroup task
51     * @defgroup task_sync Thread's synchronization
52     *
53     * @par
54     * A task, in the PEAK's context, might process events in parallel, with
55     * the help of kernel threads (pthread(3)).
56     *
57     * @par
58     * The PEAK library provides a set of functions for kernel threads
59     * synchronization within a task. If the task has only one thread to process
60     * events, these functions do nothing. Otherwise, they are prefered to more
61     * low level primitives as some optimizations can be done within a task. Be
62     * careful if you need to synchronize with other threads which are not
63     * related to a PEAK's task (eg. another thread in your program created
64     * explicitely): in that case you need more general primitives.
65     *
66     * @par
67     * When in doubt, for example if you are not very familiar with threads
68     * synchronization primitives like mutex, conditions or semaphores, you have
69     * always the choice to configure your PEAK's task to not use more
70     * than one thread (see peak_task_set_info()) Then, all the problems are over
71     * because events aren't processed in parallel anymore and you have only one
72     * excecution stream. For most applications, that will do... several events
73     * libraries act this way and are already very efficient. But, although you
74     * don't block when processing events (and you must not!), if your event's
75     * processings are still consuming significative CPU time (eg. cache search
76     * for each event, huge I/O's, etc), PEAK task capabilities of processing
77     * multiple events in the same time has shown global improvement for the
78     * application.
79     *
80     * @par
81     * Note: Synchronization between several PEAK's tasks are not yet available,
82     * as you can only have one task in the current version of the library.
83     */
84     /*!
85     * @ingroup task
86     * @defgroup task_timer Task and timer
87     *
88     * Timers are special objects which must be explicitely added to the task.
89     * See peak_timer_create() and other timer functions for more info.
90     */
91     #include <peak/stdint.h>
92     #include <peak/timer.h>
93    
94    
95     /*!
96     * @ingroup task_common
97     * @brief Opaque task type.
98     *
99     * One task to rule them all...
100     */
101     typedef struct __peak_task * peak_task;
102    
103     /*!
104     * @ingroup task_sync
105     * @brief Opaque task lock type.
106     */
107     typedef struct __peak_task_lock * peak_task_lock;
108    
109     /*!
110     * @ingroup task_sync
111     * @brief Opaque task mutex type.
112     */
113     typedef struct __peak_task_mutex * peak_task_mutex;
114    
115    
116     /*!
117     * @ingroup task_common
118     * @brief Task info's flavors.
119     */
120     enum _peak_task_flavor_e
121     {
122     /*!
123     * @ingroup task_common
124     * @brief Specify the number of threads a task should run.
125     *
126     * @par Info's value
127     *
128     * Use 0 for automatic detection which depends on the number of available
129     * CPUs when you *run* the application.
130     */
131     PEAK_TASK_FLAVOR_NTHREADS,
132     /*!
133     * @ingroup task_common
134     * @brief Specify the max number of open files allowed.
135     *
136     * This defines only the max number of open files allowed to open by the
137     * PEAK library and doesn't count application-level file descriptors.
138     * WARNING: This is not true when using the basic select() engine, due to an
139     * implementation limitation.
140     *
141     * @par Info's value
142     *
143     * Use 0 to set the default specified at the library compile time
144     * (usually 256).
145     */
146     PEAK_TASK_FLAVOR_MAXFDS
147     };
148    
149     /*!
150     * @ingroup task_common
151     * @brief Task info's flavors.
152     *
153     * See the documentation for the enumeration #_peak_task_flavor_e.
154     */
155     typedef enum _peak_task_flavor_e peak_task_flavor_t;
156    
157     #if defined(__cplusplus)
158     extern "C" {
159     #endif
160    
161     /*!
162     * @ingroup task_common
163     * @brief Get the owning task of the current execution stream.
164     *
165     * A task can have several threads, but this function will reference the
166     * same task in all of them.
167     */
168     extern peak_task peak_task_self(void);
169    
170     /*!
171     * @ingroup task_common
172     * @brief Get task information.
173     *
174     * @param task The task reference.
175     * @param flavor One of the available flavor.
176     * @param info A pointer to a varying array of int, depending on the flavor.
177     * You must properly allocate it.
178     *
179     * @return 0 if successful
180     */
181     extern int peak_task_get_info(
182     peak_task task,
183     peak_task_flavor_t flavor,
184     int *info
185     );
186    
187     /*!
188     * @ingroup task_common
189     * @brief Set task information.
190     *
191     * @param task The task reference.
192     * @param flavor One of the available flavor.
193     * @param info A pointer to a varying array of int, depending on the flavor,
194     * containing the value you want to set.
195     *
196     * @return 0 if successful
197     */
198     extern int peak_task_set_info(
199     peak_task task,
200     peak_task_flavor_t flavor,
201     int *info
202     );
203    
204     /*!
205     * @ingroup task_common
206     * @brief Get task's underlying engine name.
207     *
208     * @param task The task reference.
209     *
210     * @return A pointer to the name of engine (constant).
211     */
212     extern const char * peak_task_get_engine_name(
213     peak_task task
214     );
215    
216     /*!
217     * @ingroup task_common
218     * @brief Enter and process the event loop.
219     *
220     * Block the task's master thread if no event to process nor timers to fire
221     * are found. If called with peak_task_self(), blocks the current thread and
222     * use it as the master thread.\n
223     * Returns only if there is nothing to process (ie. no timer, no registered
224     * signal, no object scheduled) or after a call to peak_task_break().\n
225     * Usually called once at the beginning (after initializations).
226     *
227     * @param task The task to run (usually peak_task_self()).
228     */
229     extern void peak_task_run(peak_task task);
230    
231     /*!
232     * @ingroup task_common
233     * @brief Terminate task's event loop.
234     *
235     * This is done asynchronously: the engine waits for events being currently
236     * processed and the blocked peak_task_run() exits.
237     *
238     * @param task The task to break (usually peak_task_self()).
239     */
240     extern void peak_task_break(peak_task task);
241    
242     /*!
243     * @ingroup task_sync
244     * @brief Acquire task execution exclusivity.
245     *
246     * This function acquires temporary exclusive task execution among all task's
247     * threads. It's usually called at the beginning of an event-callback to avoid
248     * conflicts with other events (as they might be processed in parallel), when
249     * you deal with a lot of shared data in the callback.\n
250     * This function does nothing if the task has only one running thread, and
251     * slow down event processing otherwise. Exclusive execution is garanteed
252     * in the whole callback, in fact, it's garanteed until the next event or
253     * timer on the current task.\n
254     * Note there is no parameter at all: you can only acquire exclusive execution
255     * on the current task.
256     */
257     extern void peak_task_exclusivity(void);
258    
259     /*!
260     * @ingroup task_sync
261     * @brief Create a task's lock.
262     *
263     * Allow you to lock threads in order to create critical regions, for
264     * example, within a task, with peak_task_lock_acquire(),
265     * peak_task_lock_release(), etc. Like other PEAK's objets, you can destroy
266     * a lock with peak_release(). THEY ARE ACTIVE LOCKS FOR SMALL DATA
267     * STRUCTURES PROTECTION ONLY. If you think you will have almost no collision
268     * for a critical region, they are for you.
269     *
270     * @param task The task to associated with the lock
271     * (usually peak_task_self()).
272     *
273     * @result A new \p peak_task_lock reference.
274     */
275     extern peak_task_lock peak_task_lock_create(peak_task task);
276    
277     /*!
278     * @ingroup task_sync
279     * @brief Acquire a task's lock.
280     *
281     * This function acquires a task's lock. If the lock is already owned by
282     * another thread of the task, then the calling thread will block.
283     * However, this function does nothing if the task has only one thread.
284     * If a deadlock is detected, the program will abort, so be careful with
285     * recursions! Possibly, use peak_task_lock_try().\n
286     * Note that you can only acquire a lock for the current task.
287     */
288     extern void peak_task_lock_acquire(peak_task_lock lock);
289    
290     /*!
291     * @ingroup task_sync
292     * @brief Try to acquire a task's lock.
293     *
294     * This function attempts to acquire a task's lock without blocking. The
295     * return value indicatees whether the lock was acquired.
296     * This function does nothing if the task has only one running thread and
297     * in that case always succeeds.\n
298     * Note that you can only try a lock for the current task.
299     *
300     * @retval 1 if the lock was acquired
301     * @retval 0 if the lock is already owned (busy)
302     */
303     extern int peak_task_lock_try(peak_task_lock lock);
304    
305     /*!
306     * @ingroup task_sync
307     * @brief Release a task's lock.
308     *
309     * This function releases a task's lock, so one another thread of the task
310     * can acquire it. However, this function does nothing if the task has only
311     * one thread.\n
312     * Note that you can only release a lock for the current task.
313     */
314     extern void peak_task_lock_release(peak_task_lock lock);
315    
316     /*!
317     * @ingroup task_sync
318     * @brief Hand-off a task's lock.
319     *
320     * To assume the lock's ownership, this function passes a task's lock from
321     * the calling thread to another thread of the task. The lock must be already
322     * owned by the calling thread. If no other thread is waiting for acquiring
323     * the lock, this call will block until it happens. If the task has only one
324     * running thread, this function will abort the program (because if you use
325     * this function, you want a special synchronization behaviour that can't
326     * happen with one thread only). See peak_task_set_info() to properly
327     * configure your task.\n
328     * Note that you can only hand-off a lock for the current task.
329     */
330     extern void peak_task_lock_handoff(peak_task_lock lock);
331    
332    
333    
334     /*!
335     * @ingroup task_sync
336     * @brief Create a task's mutex.
337     *
338     * Allow you to create critical regions within a task, with
339     * peak_task_mutex_lock(), peak_task_mutex_unlock(), etc. Like other PEAK's
340     * objets, you can destroy a mutex with peak_release(). Task's mutex are
341     * more suitable to create large mutual exclusion regions than task's locks
342     * are, as they shouldn't spinlock much. However, if you need to protect basic
343     * and small data structures, it might be lighter to use task's locks (eg.
344     * for a simple operation like "object->i++;" ).
345     *
346     * @param task The task to associated with the mutex
347     * (usually peak_task_self()).
348     *
349     * @result A new \p peak_task_mutex reference.
350     */
351     extern peak_task_mutex peak_task_mutex_create(peak_task task);
352    
353     /*!
354     * @ingroup task_sync
355     * @brief Lock a task's mutex.
356     *
357     * This function locks a task's \a mutex. If the mutex is already locked
358     * then the calling thread will block until the mutex becomes available.
359     * However, this function does nothing if the task has only one thread.
360     * If a deadlock is detected, the program will abort. Possibly, use
361     * peak_task_mutex_trylock().\n
362     * Note that you can only lock a mutex for the current task.
363     */
364     extern void peak_task_mutex_lock(peak_task_mutex mutex);
365    
366     /*!
367     * @ingroup task_sync
368     * @brief Try to lock a task's mutex.
369     *
370     * This function locks a task's \a mutex. If the mutex is already locked
371     * then the calling thread will block until the mutex becomes available.
372     * However, this function does nothing if the task has only one thread.\n
373     * Note that you can only lock a mutex for the current task.
374     */
375     extern void peak_task_mutex_trylock(peak_task_mutex mutex);
376    
377     /*!
378     * @ingroup task_sync
379     * @brief Unlock a task's mutex.
380     *
381     * This function unlocks a task's \a mutex. However, this function does
382     * nothing if the task has only one thread.\n
383     * Note that you can only unlock a mutex for the current task.
384     */
385     extern void peak_task_mutex_unlock(peak_task_mutex mutex);
386    
387    
388    
389     /*!
390     * @ingroup task_timer
391     * @brief Add a peak timer.
392     *
393     * Add a previously configured peak timer to the specified task. You can
394     * create a timer with peak_timer_create(). This function increases the
395     * timer's retain count, so you can safely call peak_release() on it if needed.
396     * If the timer is already added to a task, then it is first removed then
397     * added.
398     *
399     * @param task The task reference.
400     * @param ti The timer to add.
401     */
402     extern void peak_task_timer_add(peak_task task, peak_timer ti);
403    
404     /*!
405     * @ingroup task_timer
406     * @brief Remove a peak timer.
407     *
408     * Remove a timer previously added to the task and decrease its retain count.
409     * If the retain count is 0 then the timer is deleted. If the timer wasn't
410     * previously added to the task, then this function does nothing.
411     *
412     * @param task The task reference.
413     * @param ti The timer to remove.
414     */
415     extern void peak_task_timer_remove(peak_task task, peak_timer ti);
416    
417    
418     #if defined(__cplusplus)
419     }
420     #endif
421    
422     #endif /* INCLUDED_PEAK_TASK_H_ */