]>
Commit | Line | Data |
---|---|---|
769a03c3 MF |
1 | /* Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 | * Use of this source code is governed by a BSD-style license that can be | |
3 | * found in the LICENSE file. | |
4 | */ | |
5 | ||
6 | #include "queue.h" | |
7 | ||
8 | #include <pthread.h> | |
9 | #include <stdlib.h> | |
10 | ||
11 | #define MAX_QUEUE_SIZE 16 | |
12 | ||
13 | /** A mutex that guards |g_queue|. */ | |
14 | static pthread_mutex_t g_queue_mutex; | |
15 | ||
16 | /** A condition variable that is signalled when |g_queue| is not empty. */ | |
17 | static pthread_cond_t g_queue_not_empty_cond; | |
18 | ||
19 | /** A circular queue of messages from JavaScript to be handled. | |
20 | * | |
21 | * If g_queue_start < g_queue_end: | |
22 | * all elements in the range [g_queue_start, g_queue_end) are valid. | |
23 | * If g_queue_start > g_queue_end: | |
24 | * all elements in the ranges [0, g_queue_end) and | |
25 | * [g_queue_start, MAX_QUEUE_SIZE) are valid. | |
26 | * If g_queue_start == g_queue_end, and g_queue_size > 0: | |
27 | * all elements in the g_queue are valid. | |
28 | * If g_queue_start == g_queue_end, and g_queue_size == 0: | |
29 | * No elements are valid. */ | |
30 | static struct q_ele g_queue[MAX_QUEUE_SIZE]; | |
31 | ||
32 | /** The index of the head of the queue. */ | |
33 | static int g_queue_start = 0; | |
34 | ||
35 | /** The index of the tail of the queue, non-inclusive. */ | |
36 | static int g_queue_end = 0; | |
37 | ||
38 | /** The size of the queue. */ | |
39 | static int g_queue_size = 0; | |
40 | ||
41 | /** Return whether the queue is empty. | |
42 | * | |
43 | * NOTE: this function assumes g_queue_mutex lock is held. | |
44 | * @return non-zero if the queue is empty. */ | |
45 | static int IsQueueEmpty() { return g_queue_size == 0; } | |
46 | ||
47 | /** Return whether the queue is full. | |
48 | * | |
49 | * NOTE: this function assumes g_queue_mutex lock is held. | |
50 | * @return non-zero if the queue is full. */ | |
51 | static int IsQueueFull() { return g_queue_size == MAX_QUEUE_SIZE; } | |
52 | ||
53 | /** Initialize the message queue. */ | |
54 | void InitializeMessageQueue() { | |
55 | pthread_mutex_init(&g_queue_mutex, NULL); | |
56 | pthread_cond_init(&g_queue_not_empty_cond, NULL); | |
57 | } | |
58 | ||
59 | /** Enqueue a message (i.e. add to the end) | |
60 | * | |
61 | * If the queue is full, the message will be dropped. | |
62 | * | |
63 | * NOTE: this function assumes g_queue_mutex is _NOT_ held. | |
64 | * @param[in] message The message to enqueue. | |
65 | * @return non-zero if the message was added to the queue. */ | |
66 | bool EnqueueMessage(char **argv, uint32_t argc) { | |
67 | pthread_mutex_lock(&g_queue_mutex); | |
68 | ||
69 | /* We shouldn't block the main thread waiting for the queue to not be full, | |
70 | * so just drop the message. */ | |
71 | if (IsQueueFull()) { | |
72 | pthread_mutex_unlock(&g_queue_mutex); | |
73 | return false; | |
74 | } | |
75 | ||
76 | struct q_ele *msg = &g_queue[g_queue_end]; | |
77 | msg->argv = argv; | |
78 | msg->argc = argc; | |
79 | g_queue_end = (g_queue_end + 1) % MAX_QUEUE_SIZE; | |
80 | g_queue_size++; | |
81 | ||
82 | pthread_cond_signal(&g_queue_not_empty_cond); | |
83 | ||
84 | pthread_mutex_unlock(&g_queue_mutex); | |
85 | ||
86 | return true; | |
87 | } | |
88 | ||
89 | /** Dequeue a message and return it. | |
90 | * | |
91 | * This function blocks until a message is available. It should not be called | |
92 | * on the main thread. | |
93 | * | |
94 | * NOTE: this function assumes g_queue_mutex is _NOT_ held. | |
95 | * @return The message at the head of the queue. */ | |
96 | struct q_ele *DequeueMessage(void) { | |
97 | struct q_ele *message = NULL; | |
98 | ||
99 | pthread_mutex_lock(&g_queue_mutex); | |
100 | ||
101 | while (IsQueueEmpty()) { | |
102 | pthread_cond_wait(&g_queue_not_empty_cond, &g_queue_mutex); | |
103 | } | |
104 | ||
105 | message = &g_queue[g_queue_start]; | |
106 | g_queue_start = (g_queue_start + 1) % MAX_QUEUE_SIZE; | |
107 | g_queue_size--; | |
108 | ||
109 | pthread_mutex_unlock(&g_queue_mutex); | |
110 | ||
111 | return message; | |
112 | } |