I've thought about it a bit in the past but don't really like it for the following reasons. As before, you may or may not view these reasons as sufficiently valid for me deciding not to do it.
I don't see much point in creating a common parent unless I'm going to be using that parent in the code somewhere. A common parent (I'll call it "Postman" for lack of a better term) that abstracts the underlying message passing technology (queue, notifier, user event, etc.) would be very small. The Postman class can only expose those methods that are common to all child classes--essentially, "SendMsg" and "Destroy." But, if we look a little closer at SendMsg we see that the queue's SendMsg implementation has multiple optional arguments whereas the others have none. That means Postman.SendMsg won't have any optional arguments either and I've removed useful functionality from the queue class.
Two classes inheriting from a common parent should share a lot of common behavior. Events and queues share very little common behavior. True, they both can be used to send messages in an abstract sense, but that's about it. They offer very different levels of control (i.e. have different behavior.)
(True story: Several years ago when I first jumped into LVOOP with both feet I thought (as most OOP newbies do) that inheritance is the answer to most problems. I was working on a project that handled many different instruments and figured (again, as most OOP newbies do) I'd have them all inherit from a common Instrument class. After all, I have to Open and Close all of them, right?
The further I got into that project the more difficult it became to work all the functionality I needed into each instrument's Open method. On top of that, I didn't actually use Instrument.Open anywhere. The class heirarchy was an artificial constraint I had placed on myself and was contributing nothing useful to the project.)
Another reason for using inheritance is to make it easy to change functionality. For example, I'd like the PriorityQueue to be a child of the MessageQueue class. That would make it very easy for LapDog users to start a project with a MessageQueue and--if they get to a point where the project requires it--replace it with a priority queue by simply changing the constructor. Queues and user events are not interchangable by any stretch of the imagination, so there's no benefit there.
All in all, the "convenience" of having a single SendMsg method that works for both user events and queues simply isn't worth it.
Wrapping notifiers makes more sense to me from an overall api standpoint than wrapping user events and I've considered that somewhat more seriously. I haven't done it yet mostly because I haven't needed it. Queues can do a remarkably good job of duplicating Notifier functionality. There are two main things that differentiate notifiers from queues:
1. Notifiers only store the last message sent. Easily replicated using a single element lossy queue.
2. Notifiers send message copies to each receiver. (One-to-many.) Generally in my code when messages need to be copied it is done by the component that 'knows' multiple copies are needed. For example, the mediator loop of the component that 'owns' the two receiving loops copies the message when it is received and sends a copy to each loop.
I view notifiers and user events sort of like specialized queues to be used in specific situations. I find notifiers most useful when a producer generates data faster than a consumer can consume it and you don't want to throttle the producer. (i.e. You want the consumer to run as fast as possible or you have multiple consumers that consume data at different rates.) Unless those situations are present queues are more flexible, more robust, and imo (though many disagree with me) preferable to either of those for general purpose messaging.
One thing that is important (imo) for robustness is that each loop in your application have only a single mechanism for receiving messages. (Nesting say, a user event structure inside a QSM's Idle case, can easily lead to subtle timing issues that don't show up in testing.) If you have a loop that sometimes needs queue-style messages and sometimes needs notifier-style messages, that's a good indication your loop is trying to do too much. Break it out into one loop with a queue and another loop with a notifier.
One possible implementation for this kind of object is to create an array of notifiers, one for each message. It would have to have a separate table to keep track of the dequeue ordering. Another possible implementation is to use a single queue and every time a message is enqueued it iterates through the queue and replaces the previous message with the same name. A third implementation is to use a hash table. Regardless of the implementation, there are design decisions I'd have to make that end up reducing the overall usefulness for a subset of the potential users.
-When a message is replaced, should the replacement message go the rear of the queue or hold its current position?
-Since we're going to be searching and replacing data, the data structure used to store the messages and the search algorithms are going to have an impact on performance. Should I favor speed in exchange for using more memory (hash tables) or should I strive for a minimum memory footprint (array) and take the performance hit?
-Should I do the searching and replacing in the Enqueue method or Dequeue method? In other words, which loop should take the performance hit for the added functionality?
There are no absolute answers to these questions. It's up to the developer to weigh the tradeoffs and make the correct decision based on the specific project requirements, not me.
------------------
[Edit]
BTW, even though I've rejected nearly all your suggestions I do appreciate them. It challenges my thinking and forces me to justify the decisions I've made. I hope my responses are useful to others, but the act of composing responses has led to several "a ha" moments for me.