brians | 343bc11 | 2013-02-10 01:53:46 +0000 | [diff] [blame^] | 1 | #ifndef AOS_IPC_LIB_QUEUE_H_ |
| 2 | #define AOS_IPC_LIB_QUEUE_H_ |
| 3 | |
| 4 | #include "shared_mem.h" |
| 5 | #include "aos_sync.h" |
| 6 | |
| 7 | // TODO(brians) add valgrind client requests to the queue and shared_mem_malloc |
| 8 | // code to make checking for leaks work better |
| 9 | // <http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.mempools> |
| 10 | // describes how |
| 11 | |
| 12 | #ifdef __cplusplus |
| 13 | extern "C" { |
| 14 | #endif |
| 15 | |
| 16 | // Queues are the primary way to use shared memory. Basic use consists of |
| 17 | // initializing an aos_type_sig and then calling aos_fetch_queue on it. |
| 18 | // This aos_queue* can then be used to get a message and write it or to read a |
| 19 | // message. |
| 20 | // Queues (as the name suggests) are a FIFO stack of messages. Each combination |
| 21 | // of name and aos_type_sig will result in a different queue, which means that |
| 22 | // if you only recompile some code that uses differently sized messages, it will |
| 23 | // simply use a different queue than the old code. |
| 24 | // |
| 25 | // Any pointers returned from these functions can be safely passed to other |
| 26 | // processes because they are all shared memory pointers. |
| 27 | // IMPORTANT: Any message pointer must be passed back in some way |
| 28 | // (aos_queue_free_msg and aos_queue_write_msg are common ones) or the |
| 29 | // application will leak shared memory. |
| 30 | // NOTE: Taking a message from read_msg and then passing it to write_msg might |
| 31 | // work, but it is not guaranteed to. |
| 32 | |
| 33 | typedef struct aos_type_sig_t { |
| 34 | size_t length; // sizeof(message) |
| 35 | int hash; // can differentiate multiple otherwise identical queues |
| 36 | int queue_length; // how many messages the queue can hold |
| 37 | } aos_type_sig; |
| 38 | |
| 39 | // Structures that are opaque to users (defined in queue_internal.h). |
| 40 | typedef struct aos_queue_list_t aos_queue_list; |
| 41 | typedef struct aos_queue_t aos_queue; |
| 42 | |
| 43 | // Retrieves (and creates if necessary) a queue. Each combination of name and |
| 44 | // signature refers to a completely independent queue. |
| 45 | aos_queue *aos_fetch_queue(const char *name, const aos_type_sig *sig); |
| 46 | // Same as above, except sets up the returned queue so that it will put messages |
| 47 | // on *recycle (retrieved with recycle_sig) when they are freed (after they have |
| 48 | // been released by all other readers/writers and are not in the queue). |
| 49 | // The length of recycle_sig determines how many freed messages will be kept. |
| 50 | // Other code can retrieve recycle_sig and sig separately. However, any frees |
| 51 | // made using aos_fetch_queue with only sig before the recycle queue has been |
| 52 | // associated with it will not go on to the recyce queue. |
| 53 | // Will return NULL for both queues if sig->length != recycle_sig->length or |
| 54 | // sig->hash == recycle_sig->hash (just to be safe). |
| 55 | // NOTE: calling this function with the same sig but multiple recycle_sig s |
| 56 | // will result in each freed message being put onto an undefined recycle_sig. |
| 57 | aos_queue *aos_fetch_queue_recycle(const char *name, const aos_type_sig *sig, |
| 58 | const aos_type_sig *recycle_sig, aos_queue **recycle); |
| 59 | |
| 60 | // Constants for passing to opts arguments. |
| 61 | // #defines so that c code can use queues |
| 62 | // The non-conflicting ones can be combined with bitwise-or. |
| 63 | // TODO(brians) prefix these? |
| 64 | // |
| 65 | // Causes the returned message to be left in the queue. |
| 66 | // For reading only. |
| 67 | #define PEEK 0x0001 |
| 68 | // Reads the last message in the queue instead of just the next one. |
| 69 | // NOTE: This removes all of the messages until the last one from the queue |
| 70 | // (which means that nobody else will read them). However, PEEK means to not |
| 71 | // remove any from the queue, including the ones that are skipped. |
| 72 | // For reading only. |
| 73 | #define FROM_END 0x0002 |
| 74 | // Causes reads to return NULL and writes to fail instead of waiting. |
| 75 | // For reading and writing. |
| 76 | #define NON_BLOCK 0x0004 |
| 77 | // Causes things to block. |
| 78 | // IMPORTANT: #defined to 0 so that it is the default. This has to stay. |
| 79 | // For reading and writing. |
| 80 | #define BLOCK 0x0000 |
| 81 | // Causes writes to overwrite the oldest message in the queue instead of |
| 82 | // blocking. |
| 83 | // For writing only. |
| 84 | #define OVERRIDE 0x0008 |
| 85 | |
| 86 | // Frees a message. Does nothing if msg is NULL. |
| 87 | int aos_queue_free_msg(aos_queue *queue, const void *msg); |
| 88 | |
| 89 | // Writes a message into the queue. |
| 90 | // NOTE: msg must point to at least the length of this queue's worth of valid |
| 91 | // data to write |
| 92 | // IMPORTANT: if this returns -1, then the caller must do something with msg |
| 93 | // (like free it) |
| 94 | int aos_queue_write_msg(aos_queue *queue, void *msg, int opts); |
| 95 | // Exactly the same as aos_queue_write_msg, except it automatically frees the |
| 96 | // message if writing fails. |
| 97 | static inline int aos_queue_write_msg_free(aos_queue *queue, void *msg, int opts) { |
| 98 | const int ret = aos_queue_write_msg(queue, msg, opts); |
| 99 | if (ret != 0) { |
| 100 | aos_queue_free_msg(queue, msg); |
| 101 | } |
| 102 | return ret; |
| 103 | } |
| 104 | |
| 105 | // Reads a message out of the queue. |
| 106 | // The return value will have at least the length of this queue's worth of valid |
| 107 | // data where it's pointing to. |
| 108 | // The return value is const because other people might be viewing the same |
| 109 | // messsage. Do not cast the const away! |
| 110 | // IMPORTANT: The return value (if not NULL) must eventually be passed to |
| 111 | // aos_queue_free_msg. |
| 112 | const void *aos_queue_read_msg(aos_queue *buf, int opts); |
| 113 | // Exactly the same as aos_queue_read_msg, except it will never return the same |
| 114 | // message twice with the same index argument. However, it may not return some |
| 115 | // messages that pass through the queue. |
| 116 | // *index should start as 0. index does not have to be in shared memory, but it |
| 117 | // can be |
| 118 | const void *aos_queue_read_msg_index(aos_queue *queue, int opts, int *index); |
| 119 | |
| 120 | // Retrieves ("allocates") a message that can then be written to the queue. |
| 121 | // NOTE: the return value will be completely uninitialized |
| 122 | // The return value will have at least the length of this queue's worth of valid |
| 123 | // data where it's pointing to. |
| 124 | // Returns NULL for error. |
| 125 | // IMPORTANT: The return value (if not NULL) must eventually be passed to |
| 126 | // aos_queue_free_msg. |
| 127 | void *aos_queue_get_msg(aos_queue *queue); |
| 128 | |
| 129 | #ifdef __cplusplus |
| 130 | } |
| 131 | #endif |
| 132 | |
| 133 | #endif |
| 134 | |