Queues - "dereferecing pointer to incomplete type" - c

So, I'm trying to write a few tests. I have a file called listQueue.c (not shown but working) which contains a series of a bunch of function operations on 'queues'. Now my problem lies when I try to write some tests for one of the functions in listQueue.c in a separate file I called testQueue.c.
My listQueue.c:
// Creates an empty Queue
Queue createQueue (void){
Queue q = malloc (sizeof (*q));
assert(q != NULL);
q->head = NULL;
q->tail = NULL;
q->size = 0;
return q;
}
testQueue.c contains:
int main (int argc, char *argv[]){
printf("Test 1 - Testing create q\n");
Queue q = createQueue();
printf("%d", q->size);
assert(q->head == NULL);
assert(q->tail == NULL);
printf("All tests passed, createQueue works fine.\n");
return 0;
}
The 'header file' Queue.h "
typedef struct queueImp *Queue;
//Function Prototypes
Queue createQueue(void);
Now when I tried to compile it it spits out an error.
"Dereference pointer to an incomplete type." I suspect it's something to do with how I called createQueue. Any help would be appreciated. Thanks. And yes I have included Queue.h above my main!

When you deference q in main(), compiler hasn't seen the definition of struct queueImp yet. Hence, it errors out as the compiler can't determine the size of the object.
Put the defintion of struct queueImp (not sure where you have it at the moment -- I don't see anywhere in your posted code) in queue.h and make sure to include it.

Related

static initialization of queue

I'm working on a high-reliance implementation of an algorithm for an embedded system.
in main.c:
//.. in main()
int queue_buffer[QUEUE_LEN + 1] = { 0 };
Queue queue;
queue_init(&queue, QUEUE_LEN, queue_buffer);
do_things_on_queue(&queue);
//.. in main()
in queue.c:
void queue_init(Queue *q, int len, int *data) {
q->head = 0;
q->tail = 0;
q->len = len;
q->data = data; // an array of length `len + 1`
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int *data;
} Queue;
I would like to 1. have main.c to not know about Queue; and 2. not use malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
//.. in some function
Is it possible to modify queue_init in queue.cto achieve this in C99? If so, what's the best approach?
Tentative Solutions
I am aware of the technique discussed in this post yet they seems unfeasible without using malloc. I know for sure that I will simultaneously have 4 queues at most. This makes me think that I could declare a memory pool for the queues as a static global array of queues of size 4. Is it ok to use global variables in this case?
#KamilKuk suggested to just have queue_init to return the structure itself since QUEUE_LEN is known at compile time. This requires the following:
in queue.c:
Queue queue_init(void) {
Queue q;
q.head = 0;
q.tail = 0;
q.len = QUEUE_LEN;
for (int i=0; i < QUEUE_LEN; i++)
q.data[i] = 0;
return q;
}
in queue.h:
typedef struct queue {
int head;
int tail;
int len;
int data[QUEUE_LEN];
} Queue;
Queue queue_init(void);
This appears to greatly simplify the structure initialization.
However this does not solve the privacy problem, since main.c should know about Queue to initialize this struct.
Thank you.
I would like to 1. have main.c to not know about Queue; and 2. not use
malloc for intializing queue_buffer_ but rather do it statically.
this implies that ideally main.c would be:
//.. in some function
Queue queue = queue_init(something_eventually);
do_things_with_queue(&queue);
//.. in some function
No, your objectives do not imply a solution as described. You cannot declare or use an object of type Queue anywhere that the definition of that type is not visible. That follows directly from the language's rules, but if you want a more meaningful justification then consider that even if main does not access any of the members of Queue, it still needs the definition simply to know how much space to reserve for one.
It's not obvious to me that it serves a useful purpose to make type Queue opaque in main.c (or anywhere), but if that's what you want then in that scope you can forward declare it, never define it, and work only with pointers to it:
typedef struct queue Queue;
// ...
Queue *queue = queue_init(something_eventually);
do_things_with_queue(queue);
For that to work without dynamic memory allocation, the pointed-to Queue objects must have static storage duration, but that does not mean that they need to be globals -- either in the sense of being accessible via a name with external linkage, or in the sense of being declared at file scope.
Additionally, you have the option of allocating the data arrays automatically, as in your example code, so as to not tie up that memory in queues when they are not in use. If you prefer, you can wrap that up in a macro or two for a bit of additional ease of use (left as an exercise).
For example,
queue.h
typedef struct queue Queue;
Queue *queue_init(int queue_size, int queue_data[]);
void queue_release(Queue *queue);
queue.c
#include "queue.h"
struct queue {
int head;
int tail;
int len;
int *data;
};
Queue *queue_init(int queue_len, int queue_data[]) {
// queue_pool has static storage duration and no linkage
static Queue queue_pool[4] = {{0}};
// Find an available Queue, judging by the data pointers
for (Queue *queue = queue_pool;
queue < queue_pool + sizeof(queue_pool) / sizeof(*queue_pool);
queue++) {
if (queue->data == NULL) {
// This one will do. Initialize it and return a pointer to it.
queue->head = 0;
queue->tail = 0;
queue->len = queue_len;
queue->data = queue_data;
return queue;
}
}
// no available Queue
return NULL;
}
void queue_release(Queue *queue) {
if (queue) {
queue->data = NULL;
}
}
main.c
// ... in some function
int queue_data[SOME_QUEUE_LENGTH];
Queue *queue = queue_init(SOME_QUEUE_LENGTH, queue_data);
do_things_with_queue(queue);
queue_release(queue);
// ...
Of course, if you prefer, you can put the queue data directly into the queue structure, as in your tentative solution, and maybe provide a flag there to indicate whether the queue is presently in use. That would relieve users of any need to provide storage, at the cost of tying up the storage for all the elements of all the queues for the whole duration of the program.
The best way to do this is to pass a buffer and its size to the init function, exactly as you already have.
It is a very bad idea to worry about calling a function versus having the data fixed at compile time. Both the execution time and code size for a tiny initialization like this is negligible. Making your code interface awkward just to save a few instructions at startup is not just a waste of effort, it makes the code hard to maintain and risks introducing bugs.
There are a number of embedded systems or libraries that provide a macro which declares both the storage array and the control structure in one go and gives them a name which is known only to the library, and then you have to use a macro to generate the name every time you access the item. For an example of this you might look at osMailQDef in CMSIS-OS. I don't really recommend this method though. It is too easy to get wrong, whereas doing it the usual way is easy to read and any reviewer will be able to spot a mistake straight away.
I would typically do:
// queue.h
#define QUEUE_INIT(data, len) { .len = len, .data = data }
#define QUEUE_INIT_ON_STACK(len) QUEUE_INIT((char[len]){0}, len)
// main.c
static Queue queue = QUEUE_INIT_ON_STACK(QUEUE_LEN + 1);
As for PIMPL idiom, it's easy to implement with descriptors just like file descriptors in LINUX, especially when the count is static.
// queue.h
typedef Queue int;
void do_things_with_queue(Queue);
// queue.c
struct RealQueue { stuff; };
static struct RealQeueue arr[4] = { stuff };
static struct RealQeueue *get_RealQueue(Queue i) {
assert(0 <= i && i < sizeof(arr)/sizeof(*arr));
return &arr[i];
}
void do_things_with_queue(Queue i) {
struct RealQueue *queue = get_RealQueue(i);
}
// main.c
static Queue queue = 1;
// etc.
Or you can break all hell and synchronize alignment between source and header file:
// queue.h
struct Queue {
// This has to be adjusted __for each compiler and environment__
alignas(60) char data[123];
};
#define QUEUE_INIT() { 0xAA, 0xBB, etc.. constant precomputed data }
// queue.c
struct RealQeueue { stuff; };
static_assert(alingof(struct RealQueue) == alignof(struct Queue), "");
static_assert(sizeof(struct RealQueue) == sizeof(struct Queue), "");
void do_things_with_queue(Queue *i) {
struct RealQueue *queue = (struct RealQueue*)i->data;
}

How can I create a function object in C

I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p

Binary Tree of Strings returning wrong order

I am fairly new to C and have been learning from K&R's book The C Programming Language.
After doing the exercises on Binary trees I wanted to make a header for binary trees for
char*, long and double.
There is a function in the following code that has been giving me grief - it should fill an array of character pointers with the values stored in the tree in lexicographical order however it has a bug somewhere. Here's the code for the String Tree Header btree.h:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/************** TYPES **************/
typedef struct ctree
{
char *name;
ctree *left;
ctree *right;
};
/************** Globals **************/
static int c_inc = 0;
/************** Function Prototypes **************/
ctree *add_to_c_tree (ctree *cnode, char *name);
void print_c_tree (ctree *cnode);
ctree *c_tree_alloc (void);
void c_tree_free (ctree *cnode);
void return_c_tree (ctree *cnode, char **array);
/************** Function Definitions **************/
/* add_to_c_tree() : Adds a new node to a *character binary tree */
ctree *add_to_c_tree (ctree *cnode, char *name){
/* If the node is null, allocate memory for it,
* copy the name and set the internal nodes to null*/
if(cnode == NULL){
cnode = c_tree_alloc();
cnode->name = strdup(name);
cnode->left = cnode->right = NULL;
}
/* If initialised then add to the left node if it is lexographically
* less that the node above it else add it to the right node */
else{
if(strcmp(name, cnode->name) < 0)
cnode->left = add_to_c_tree(cnode->left,name);
else if(strcmp(name, cnode->name) > 0)
cnode->right = add_to_c_tree(cnode->right,name);
}
return cnode;
}
/* print_c_tree() : Print out binary tree */
void print_c_tree(ctree *cnode){
if (cnode != NULL) {
print_c_tree(cnode->left);
printf("%s\n",cnode->name);
print_c_tree(cnode->right);
}
}
/* return_c_tree() : return array of strings containing all values in binary tree */
void return_c_tree (ctree *cnode, char **array){
if (cnode != NULL) {
return_c_tree (cnode->left,array+c_inc);
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
// printf("arr+%d:%s\n", c_inc-1,*(array+(c_inc-1)));
return_c_tree (cnode->right,array+c_inc);
c_tree_free(cnode->right);
}
}
/* c_tree_alloc() : Allocates space for a tree node */
ctree *c_tree_alloc(void){
return (ctree *) malloc(sizeof(ctree));
}
/* c_tree_free() : Free's Memory */
void c_tree_free (ctree *cnode){
free(cnode);
}
Which I have been testing with bt.c:
#include "btree.h"
int main(void){
ctree *node = NULL; char *arr[100];
node = add_to_c_tree(node, "foo");
node = add_to_c_tree(node, "yoo");
node = add_to_c_tree(node, "doo");
node = add_to_c_tree(node, "woo");
node = add_to_c_tree(node, "aoo");
node = add_to_c_tree(node, "boo");
node = add_to_c_tree(node, "coo");
print_c_tree(node);
return_c_tree(node,arr);
for (int i = 0; i < 7; ++i)
{
printf("%d:%s ..\n",i, arr[i]);
}
return 0;
}
The reason for this question is that I have been having issues with the return_c_tree() function, which is meant to mimic the behaviour of K&R's print_c_tree() function except instead of recursively calling itself until a NULL ptr and printing out the name of the nodes in lexicographical order it is meant to add their names to an array of character ptrs and free the nodes memory.
However the output I get when run as above is:
aoo
boo
coo
doo
foo
woo
yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which shows that the print function works fine but the return function obviously isn't.
The confusing thing is that if the call to printf() in return_c_tree() is uncommented this is the result:
aoo
boo
coo
doo
foo
woo
yoo
arr+0:aoo
arr+1:boo
arr+2:coo
arr+3:doo
arr+4:foo
arr+5:woo
arr+6:yoo
0:aoo ..
1:(null) ..
2:boo ..
3:doo ..
4:foo ..
5:coo ..
6:(null) ..
Which implies that it actually does add the strings in the right order.
Also I have tried it without the c_inc variable -> ie just incrementing array
before passing it to the right node which the produces the same results from the printf
in return_c_tree() but different from main:
arr+-1:aoo
arr+-1:boo
arr+-1:coo
arr+-1:doo
arr+-1:foo
arr+-1:woo
arr+-1:yoo
0:foo ..
1:yoo ..
2:coo ..
3:(null) ..
4:(null) ..
5:(null) ..
6:(null) ..
I'm rather confused, so If anyone can help I would appreciate it greatly. I'm sure I'm just incrementing it in the wrong place but I can't work out where.
I thought I had finally understood pointers but apparently not.
Best
P
Your problem is how you handle your pointer to array when you recursively call. This will fix your return_c_tree function:
void return_c_tree (ctree *cnode, char **array)
{
if (cnode != NULL) {
return_c_tree (cnode->left,array); // <--- CHANGED 2ND PARAM
c_tree_free(cnode->left);
*(array+c_inc++) = strdup(cnode->name);
return_c_tree (cnode->right,array); // <--- AGAIN, CHANGED 2ND PARAM
c_tree_free(cnode->right);
}
}
You're using a global variable c_inc to keep track of the current index into the array. However, when you recursively called return_c_tree, you passed in array+c_inc, but you did not offset c_inc to account for this. Basically, you double-counted c_inc each time.
While this solves your particular problem, there are some other problems with your code.
In general, using global variables is asking for trouble. There's no need to do it here. Pass c_inc as a parameter to return_c_tree.
Also, mixing global variables with recursion is especially prone to problems. You really want recursive routines to keep their state on the stack.
As a commenter pointed out, all of your code in btree.h should really be in btree.c. The point of header files is to define an interface, not for code.
(This is more stylistic) Your return_c_tree function is really two distinct functions: copy the elements of the tree (in order) into the array, and free the memory used by the tree. These two operations are conceptually distinct: there are times that you'll want to do one and not both. There can be compelling performance (or other) reasons to mix the two, but wait until you have some hard evidence.

Passing queue as parameter in c

I am passing queues like these between source files a.c and b.c
File : a.c
sq[a]=new_queue();
pthread_create(&st[a],NULL,sendPacket,sq[a]);
File : b.c
void *sendPacket(void *queue){
/* here i need to know which queue has come ,determine
the index of queue how can I do it? */
}
Create a more high-level representation of your queue. It seems the queue can be a void * (you're not showing its actual type, i.e. what does the new_queue() call return?), so embed that in a structure while adding the additional parameters:
struct queue_state {
void *queue;
int index;
};
Then instantiate a structure, and pass a pointer to it to the thread function:
struct queue_state qsa = malloc(sizeof *qsa);
if(qsa != NULL)
{
qsa->queue = new_queue();
qsa->index = 4711; /* or whatever */
pthread_create(&st[a], NULL, sendPacket, qsa);
}
Then the thread function can use the struct declaration to access all the fields. Of course, the declaration needs to be in a shared header (say queue.h) which is included from both C files.
Your question description is very rough. But at least from what I understand, you actually need to pass 2 parameters to your function: the (pointer to) queue (which seems an array for me), and the index within this queue.
You may not pack both your parameters in a single variable of type void*. What you may do is declare a struct with all the needed parameters, fill it, and pass a pointer to it to your thread.
Like this (error handling omitted):
struct Params
{
queue* m_Queue;
size_t m_Idx;
};
// ...
Params* pParams = new Params;
pParams->m_Queue = sq;
pParams->m_Idx = a;
pthread_create(&st[a],NULL,sendPacket, pParams);
void *sendPacket(void *pPtr)
{
Params* pParams = (Params*) pPtr;
// ...
delete pParams;
}
Probably it is easier if you just pass the index to the function:
void *sendPacket(int queue_idx) {
queue_t *queue = &sq[queue_idx];
}
If in b.c you have access to sq, you can just pass the index to the queue. Otherwise you can pass a struct containing the actual queue and the index

Lock-free queue

Also I am doing a c implementation and currently have the structure of the queue:
typedef struct queueelem {
queuedata_t data;
struct queueelem *next;
} queueelem_t;
typedef struct queue {
int capacity;
int size;
queueelem_t *head;
queueelem_t *tail;
} queue_t;
queue_t *
queue_init(int capacity)
{
queue_t *q = (queue_t *) malloc(sizeof(queue_t));
q->head = q->tail = NULL;
q->size = 0;
q->capacity = capacity;
return q;
}
int CompareAndExchange (void **a, void *comparand,void *new) {
int success = 0;
pthread_mutex_lock(&CE_MUTEX);
if ((*a) != comparand) {
(*a) = new;
//return TRUE
success = 1;
}
pthread_mutex_unlock(&CE_MUTEX);
//return FALSE
return success;
}
But not sure How to continue, with queue and dequeue functions...
How would the code look like?
Sometime ago, I've found a nice solution to this problem. I believe that it the smallest found so far.
The repository has a example of how use it to create N threads (readers and writers) and make then share a single seat.
I made some benchmarks, on the test example and got the following results (in million ops/sec) :
By buffer size
By number of threads
Notice how the number of threads do not change the throughput.
I think this is the ultimate solution to this problem. It works and is incredible fast and simple. Even with hundreds of threads and a queue of a single position. It can be used as a pipeline beween threads, allocating space inside the queue.
The repository has some early versions written in C# and pascal. Im working to make something more complete polished to show its real powers.
I hope some of you can validate the work or help with some ideas. Or at least, can you break it?
Your pseudo-code can (and most likely does) suffer from the ABA problem, as only the pointer is checked, and not an accompanying unique stamp, you'll find this paper of use in that regard and as a general guide to lock-free queue implementation, with its pitfalls.
When dealing with lock free programing, its also a good idea to read up on Herb Sutter's works, as He gives good, insightful explanations to whats required, why its required and its potential weak points (though beware that some of his older publications/articles where found to contain some hidden/unforseen problems).
and also the recent boost'con talk about this subject :
https://github.com/boostcon/2011_presentations/raw/master/wed/lockfree_2011_slides.pdf
(Leaving this here for now, but see edit.)
Do you know a implementation of lock free queue in C?
I wrote lockless queue recently (http://www.ideone.com/l2QRp). I can't actually guarantee it works correctly, but I can't find any bugs and I've used it in a couple of single threaded programs without any problems, so there's nothing too obvious wrong with it.
Trivial usage example:
queue_t queue;
int val = 42;
queue_init(&queue,sizeof val);
queue_put(&queue,&val);
val = 0;
queue_pop(&queue,&val);
printf("%i\n",val); // 42
queue_destroy(&queue);
Edit:
As #Alexey Kukanov pointed out, queue_pop can fail if tmp is popped,freed,allocated again, and put again between checking for null and swapping:
if(!tmp->next) return errno = ENODATA;
/* can fail here */
} while(!sync_swap(q->head,tmp,tmp->next));
I'm not yet sure how to fix this, but I'll (hopefully) update this once I figure it out. For now, disregard this.
You may try this library it is built in c native. lfqueue
For Example
int* int_data;
lfqueue_t my_queue;
if (lfqueue_init(&my_queue) == -1)
return -1;
/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
while (lfqueue_enq(&my_queue, int_data) == -1) {
printf("ENQ Full ?\n");
}
/** Wrap This scope in other threads **/
/*Dequeue*/
while ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
printf("DEQ EMPTY ..\n");
}
// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/
lfqueue_destroy(&my_queue);

Resources