Впрочем, я кажется понимаю в чем проблема такого подхода - кто-нибудь может взять, и сохранить переданный ему указатель на сообщение для неких своих нужд.
Расскажу про свою библиотеку Intercom (на C#). У меня сообщение передаётся во владение. Хочешь сохраняй, не хочешь - вызывай Dispose. В Dispose объект сообщения помещается в кэш для повторного использования. Кэш в принципе бесконечный, но раз в минуту он очищается на 10%. Есть два типа диспетчеров службы доставки сообщений: однопоточный и многопоточный. Многопоточный диспетчер может доставить одному и тому же получателю несколько сообщений одновременно. Объекты-получатели для того чтобы стать получателями должны зарегистрироваться в диспетчере. При регистрации им выдаётся интеркомный адрес Intercom.Id. Это 8 байтовое число, в котором закодирован диспетчер и номер зарегистрированного объекта. Отправка сообщения осуществляется по идентификатору Intercom.Id получателя.
Intercom.SendMessage(идентификатор_получателя, указатель_на_сообщение);
Отправляемое сообщение ставится в очередь. Затем из потока(потоков) диспетчера доставляется. Получатель может разрегистрироваться, тогда во время доставки диспетчер не найдёт объекта с указанным Intercom.Id, в этом случае у сообщения будет вызван Dispose самим диспетчером. У однопоточного диспетчера реализована возможность широковещательной рассылки сообщения всем зарегистрированным в этом диспетчере подписчикам. Это сообщение диспозится самим диспетчером, получатели не должны изменять широковещательные сообщения. Сообщения бывают первого и второго сорта (приоритета). В среднем, на каждые 10 сообщений первого сорта (если они есть) будет обработано 1 сообщение второго сорта (если оно есть). Имеется встроенный неотключаемый профилировщик, который постоянно измеряет сообщения каких типов каким типам получателей сколько раз в секунду доставляются и сколько времени обрабатываются. Измеряется длина очередей (первого и второго сорта) в секундах (латентность). Скорость отправки сообщений, скорость доставки (когда система перегружена первая скорость будет больше второй, а очередь будет расти). Программа использующая Intercom знает сколько времени сообщения простаивают в очереди (латентность) и может регулировать нагрузку. Если речь о телефонных звонках, то программа может режектить лишние телефонные звонки адаптируясь под быстродействие железа, удерживая латентность (время отклика) в заданных пределах. Имеется встроенный неотключаемый контролёр, который следит за зависаниями. Если кто-то получая сообщение слишком долго не возвращает управление, то контролёр (у него отдельный поток) печатает в журнал тип сообщения, тип получателя и сколько секунд уже тянется получение сообщения, ругаясь на то, что возможно программа зависла. Через определённый большой таймаут (убедившись, что поток точно завис и терять уже нечего кроме своих цепей) контролёр делает попытку абортировать поток диспетчера с целью получить стэк трэйс того места кода где произошло зациклиливание.
namespace MeraSystems
{
public static partial class Intercom
{
public static void Subscribe (Dispatcher d, Object obj);
public static void Unsubscribe (Object obj);
public static void SendMessage (Id intercomId, Message message);
public static void SendSecondGradeMessage (Id intercomId, Message message);
public static void BroadcastMessage (Dispatcher dispatcher, Message message);
public static void BroadcastSecondGradeMessage (Dispatcher dispatcher, Message message);
public static void Terminate ();
public static Dispatcher CreateDispatcher (string name, SinglethreadHook hook);
public static Dispatcher CreateDispatcher (string name, MultithreadHook hook, int minThreadCount, int maxThreadCount);
public static void WriteReport (System.Collections.Generic.List<string> report); // отчёт профилировщика
}
}