in reply to Linked lists in an array of hashes

First: big kudos for seeing that data structures are important and working to learn about them. I think some of the other posters may be missing what you're trying to do here: use a language that you're comfortable in to try to understand computer science concepts, not solve a particular problem.

The comments that note that arrays manage themselves in Perl are certainly true, it's that, if I'm interpreting your question correctly, you want to learn about traditional data structure management.

So - you have then empty condition correct: if the head and tail point to the same node, the buffer is empty. A clearer statement of the "full" state is "If the next of the tail node points to the head, then the buffer is full".

First: setting up a ring buffer programatically rather than declaratively. You want an array (fixed size) of hashes, each one "pointing" to the next except for the last, which should point to the first. So let's do that:

my @ring; use constant RING_SIZE => 10; for my $buffer_pointer (0..RING_SIZE) { my $next_element = ($buffer_pointer + 1) % RING_SIZE; $ring[$buffer_pointer] = { data =>'', next => $next_element }; }
I initially also had put together an example of using references to build a "real" circular buffer, but really there's no reason to do it: way too much overhead. (Aside: it showed me my pointer manipulation skills are a little stale! Worth trying yourself for that reason.) Ring buffers generally are used when you've got the following situation:
  1. You have one thread or process reading a buffer, and a second one writing it.
  2. You are memory-constrained and can only afford to devote a controlled, relatively small amount of storage to the process
  3. You want relatively fast response time from both processes.
So the writer gets characters from somewhere, and puts them into the buffer. If the buffer fills, it blocks until there is room in the buffer again. The reader of course does the opposite: if the buffer is empty, it blocks until something appears there.

You do, as others have also mentioned, need a lock to serialize access to the buffer, since the operations to manage the buffer are not atomic - it takes more than one step to decide that there's something in it (or room available) and then alter the buffer accordingly. If you were really planning on implementing this for some reason (a pool of reusable database handles?), you'd need the locking. And they're also right that implementing the put/get management with shift and push would probably be far more efficient and easier to debug.