Good stuff, thanks for sharing. Random comments based on a quick glance through the code if I may.<p><pre><code> chan_t* chan_init(int capacity);
</code></pre>
should be "size_t capacity", since negative capacity values are invalid. This also eliminated the need for the first check in the function.<p><pre><code> chan->buffered
</code></pre>
is duplicate in meaning to chan->queue being non-NULL.<p>Why chan's mutexes and pcond are malloc'ed and not included in chan's struct? They are also not freed when channel is disposed, unless I'm missing something. Mutexes are also not destroyed when buffered chan is disposed, but they <i>are</i> created for it.<p>(Edit)<p>Also, my biggest nitpick would be that chan_t structure should really not be in chan.h header since it's meant to be transparent to the app and the API operates exclusively with pointers to chan_t. Then, if it is made private (read - internal to the implementation), then you can divorce buffered and unbuffered channels into two separate structs, allocate required one and then multiplex between them in calls that treat buffered and unbuffered channels differently. I.e.<p><pre><code> struct chan_t
{
// Shared properties
pthread_mutex_t m_mu;
pthread_cond_t m_cond;
int closed;
// Type
int buffered;
};
struct chan_unbuffered_t
{
struct chan_t base;
pthread_mutex_t r_mu;
pthread_mutex_t w_mu;
int readers;
blocking_pipe_t* pipe;
};
...
</code></pre>
or better yet, just include a handful of function pointers into chan_t for each of the API methods that need more than the shared part of chan_t struct, initialize them on allocation and put type-specific code in these functions. It will make for a more compact, concise and localized code.<p>(Edit 2)<p>Here's what I mean with function pointers - <a href="https://gist.github.com/anonymous/5f97d8db71776b188820" rel="nofollow">https://gist.github.com/anonymous/5f97d8db71776b188820</a> - basically poor man's inheritance and virtual methods :)