-
Notifications
You must be signed in to change notification settings - Fork 121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
memory not freed #1
Comments
@je-so I added numbers to your comment so I could address each item.
|
|
The other reason the pipe is useful is when a channel is closed. In the event that a reader is blocked waiting, closing a channel needs to unblock the reader and have it return -1. This could probably be implemented without the pipe, but it would require the chan to signal the pipe's cond and the pipe reader to check if the chan has been closed. One option might be to add a field on the blocking pipe struct I suppose writing/reading from a pipe is significantly slower than simply assigning the void pointer though. |
Yep. Writer: Uses a simple queue which can store 16 void* and calls put_voidptrm which searches the next free entry waiting on condition_notfull if queue is full. Reader: Calls get_voidptr, reading from head of queue and waiting on condition_notempty if queue is empty. Reading signals condition_notfull and writing signals condition_notempty. Closing the chan flushes the queue (removing unprocessed content). If you have many readers and writers and the channel could be closed and freed any time |
Point 3: How do you make sure that the content where the pointer points to is valid? I thought about the problem and implemented an experimental message queue See https://github.com/je-so/iqueue/blob/master/README.md for an example how the What do you think? |
That looks like a reasonable solution. The problem with chan is I'd like to maintain the semantics of Go channels as much as possible. I think this would break from those semantics. A way to send/recv buffers safely was implemented using memcpy (https://github.com/tylertreat/chan/blob/master/src/chan.c#L591). Zero-copy is really nice, but I think this matches the semantics of Go more. |
I think instead of calling chan_send_buf and chan_recv_buf it is much faster to send a pointer to But I can see the point of being compatible with Go channels which employ value semantics. Then wouldn't it be faster to store the whole value in chan instead of a pointer to a malloced value? If you'd provide an elemsize parameter in the init function and change recv and send to transfer elemsize bytes instead of a single pointer chan would reflect the value semantics of GO even more. You also have to provide the type (== elemsize) parameter in the declaration of a Go channel :-) |
Yes, there has been some discussion on "typed" channels (#7), but I agree that specifying an elemsize in init would probably be a better solution. It would indeed closer match the semantics of Go since you have to specify a type when creating a channel. |
If have experimented with iqueue and added a type safe feature which is implemented in macro iqueue_DECLARE (see https://github.com/je-so/iqueue/blob/master/include/iqueue.h at the bottom). You could use the same technique to make chan type safe (after you have added support for elemsize of course :-)). (example 3 shows how to use the macro). |
Yeah, that looks really nice! |
Where is the corresponding free?
void_ msg;
chan_recv(chan, &msg);
printf("%s\n", msg);
// missing free(msg)
chan_recv(chan, &msg);
printf("%s\n", msg);
// missing free(msg)
It is much simpler to synchronize with pthread_cond_wait and write a pointer into a data field of blocking_pipe_t*. You do not need any pipe in this case.
What about the following ?
void* ping() {
char localstr[] = { "ping" };
chan_send(chan, localstr);
return NULL;
}
This causes undefined behaviour. Your synchronization in blocking_pipe_t synchronizes
only the pointer transfer but does not make sure that the receiving end has processed
the data the pointer is pointing to !!
unbuffered_chan_recv(chan_t* chan, void** data)
{
pthread_mutex_lock(&chan->r_mu);
if (chan_is_closed(chan))
{
// missing _unlock !!
errno = EPIPE;
return -1;
}
(No more time to check for more errors :-))
The text was updated successfully, but these errors were encountered: