Priority Queues

Ulf Wiger (AL/EAB) ulf.wiger@REDACTED
Mon May 16 14:29:46 CEST 2005


You can do this (almost) using an ordered_set disc_copy
table in mnesia. The object key could be e.g. 
{Priority, erlang:now()} for prioritized FIFO, or
{Priority, negative(erlang:now())} for prioritized LIFO,
where

negative({MSec, Sec, MuSec}) ->
  {-MSec, -Sec, -MySec}.


1) Using dirty_first(Tab) and dirty_last(Tab), you can
   get to the first and last entries respectively.

2) The structure of the key determines the ordering.
   See above.

3) Not a big problem, but the entries will all be in 
   RAM (and logged to disk periodically)

4) Not constant time, but close enough (logN)

5) Persistence is taken care of by mnesia

6) To make this thread-safe, you need to either 
   serialize the operation using a server, or use 
   mnesia transactions. The transaction can for example
   return the next value for processing like so:
  
   mnesia:activity(
        dirty,
        fun() ->
            case mnesia:dirty_first(prio_queue) of
                '$end_of_table' -> queue_empty;
                Key ->
                    [Result] = mnesia:read(prio_queue, Key, write),
                    mnesia:delete(prio_queue, Key)
                    Result
            end
        end).

It's a little trickier if you want full atomicity, since there
is no mnesia:first/1. You can still do it like described above,
since you get synchronization on the read, and thus avoid the 
risk of race conditions or lost updates. However, you can get 
aborted transactions instead of proper serialization.

It's possible to use mnesia:select(Tab, Pattern, 1, write), 
which will, on an ordered_set, return the first object in the 
table matching Pattern, but it will be slightly more expensive
(esp. if this operation is called as a nested transaction, since 
the select() call has to scan the transaction store.)

Of course, the overhead of using transactions will be significant,
but mnesia:activity(dirty, ...) is not so bad. It's a very handy
way of packaging dirty operations.

/Uffe

> -----Original Message-----
> From: owner-erlang-questions@REDACTED
> [mailto:owner-erlang-questions@REDACTED]On Behalf Of 
> Rudolph van Graan
> Sent: den 16 maj 2005 08:24
> To: Erlang Questions
> Subject: Priority Queues
> 
> 
> Hi All,
> 
> I am currently thinking about the implementation of priority queues  
> in erlang. Specifically, what do you guys suggest as an 
> efficient way  
> to achieve the following:
> 
> 1. A queue with a definitive head and tail (i.e. first and 
> last records)
> 2. The items in the queue need to be sorted according to some  
> criteria that will always allow you to identify an entry as the  
> "first" or "next" one
> 3. The queue length can be massive (100's of thousands or 
> millions of  
> records)
> 4. Insertion time should be constant
> 5. The queue must be persistent (i.e. mnesia or dets)
> 6. Once the first/head entry has been processed, it will no 
> longer be  
> in the queue.
> 
> Any suggestions?
> 
> Rudolph van Graan
> 
> 



More information about the erlang-questions mailing list