Developing Apama Applications > Developing Apama Applications in EPL > Common EPL Patterns > Reference counting
Reference counting
The following pattern is another example that you can use to to keep a count of how many clients are using a particular service object, which in turn can be used to determine the lifetime of these service objects. The example subscription management mechanism is fairly sophisticated, possibly too sophisticated, but it provides the big advantage of separating the concerns by using two monitors. If you decide to change the subscription mechanism, you can do so simply by changing the ServiceManager monitor. There is no impact at all on the ServiceItem monitor.
The events:
package com.apamax.service;
event Subscribe {
   string toWhat;
   string originator;
}
event Unsubscribe {
   string fromWhat;
   string originator;
}
event CreateServiceItem {
   string what;
}
event DestroyServiceItem {
   string what;
}
The monitors:
monitor ServiceManager {
   dictionary < string, dictionary < string, integer > > items;
 
   action onload() {
      Subscribe s;
      Unsubscribe u;
      on all Subscribe():s subscribe(s);
      on all Unsubscribe():u unsubscribe(u);
   }
 
   action subscribe(Subscribe s){
      if items.hasKey(s.toWhat) then {
         dictionary < string, integer > subscriptions :=
            items[s.toWhat];
         if subscriptions.hasKey(s.originator) then {
            subscriptions[s.originator] :=
               subscriptions[s.originator] + 1;
         }
         else {
            subscriptions[s.originator] := 1;
         }
      }
      else {
         items[s.toWhat] := subscriptions;
         route CreateServiceItem(s.toWhat);
      }
   }
 
   action unsubscribe(Unsubscribe u) {
      if items.hasKey(u.fromWhat) then {
         dictionary < string, integer > subscriptions :=
            items[u.fromWhat];
         if subscriptions.hasKey(u.originator) then {
            if subscriptions[u.originator] <= 1 then {
               subscriptions.remove(u.originator);
               if subscriptions.size() = 0 then {
                  items.remove(u.fromWhat);
                  route DestroyServiceItem(u.fromWhat);
               }
            }
            else {
               subscriptions[u.originator] :=
                  subscriptions[u.originator] - 1;
            }
         }
         else {
            print "Unsubscribe failed: no originator: " +
               u.toString();
         }
      }
      else {
         print "Unsubscribe failed: no item: " + u.toString();
      }
   }
}
 
monitor ServiceItem {
   //...
 
   action onload() {
      CreateServiceItem c;
      on all CreateServiceItem():c spawn createServiceItem(c);
   }
 
   action createServiceItem(CreateServiceItem c) {
   //...
      DestroyServiceItem d;
      on all DestroyServiceItem():d destroyServiceItem(d);
   }
 
   action destroyServiceItem(DestroyServiceItem d) {
   //...die;
   }
}
Copyright © 2013 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or Terracotta Inc., San Francisco, CA, USA, and/or Software AG (Canada) Inc., Cambridge, Ontario, Canada, and/or, Software AG (UK) Ltd., Derby, United Kingdom, and/or Software A.G. (Israel) Ltd., Or-Yehuda, Israel and/or their licensors.