@@ -198,7 +198,12 @@ static bool s_bInstalled = false;
198198#define s_mapTimered s_staticdata.mapTimered
199199#define s_mapHandle s_staticdata.mapHandle
200200
201+ #define s_mapSubscribedIndex 0
202+ #define s_mapServicedIndex 1
203+ #define s_mapTimeredIndex 2
204+
201205pointer K_ROSEUS_MD5SUM,K_ROSEUS_DATATYPE,K_ROSEUS_DEFINITION,K_ROSEUS_CONNECTION_HEADER,K_ROSEUS_SERIALIZATION_LENGTH,K_ROSEUS_SERIALIZE,K_ROSEUS_DESERIALIZE,K_ROSEUS_INIT,K_ROSEUS_GET,K_ROSEUS_REQUEST,K_ROSEUS_RESPONSE,K_ROSEUS_GROUPNAME,K_ROSEUS_ONESHOT,K_ROSEUS_LAST_EXPECTED,K_ROSEUS_LAST_REAL,K_ROSEUS_CURRENT_EXPECTED,K_ROSEUS_CURRENT_REAL,K_ROSEUS_LAST_DURATION,K_ROSEUS_SEC,K_ROSEUS_NSEC,QANON,QNOOUT,QREPOVERSION,QROSDEBUG,QROSINFO,QROSWARN,QROSERROR,QROSFATAL;
206+ pointer QSTATICDATAVECTOR, K_ROSEUS_ENTER, K_ROSEUS_DELETE;
202207extern pointer LAMCLOSURE;
203208
204209/* **********************************************************
@@ -256,14 +261,21 @@ int getInteger(pointer message, pointer method) {
256261 return 0 ;
257262}
258263
259- void store_pointer (context *ctx, pointer value) {
260- // Stores a callback list as a symbol in the lisp package.
264+ void store_pointer (context *ctx, string name, int index, pointer value) {
265+ // Stores a callback list in ros::*static-data-vector*
261266 // This prevents that the callable gets collected by the gc,
262267 // even if there are no other references to it.
263- // TODO: cleanup when unsubscribed
264268 vpush (value);
265- pointer p=gensym (ctx);
266- defconst (ctx, (char *)(p->c .sym .pname ->c .str .chars ), vpop (), lisppkg);
269+ pointer p=makestring ((char *)name.c_str (), name.size ());
270+ csend (ctx,speval (QSTATICDATAVECTOR)->c .vec .v [index],K_ROSEUS_ENTER,2 ,p,vpop ());
271+ }
272+
273+ void erase_pointer (context *ctx, string name, int index) {
274+ // Removes the entry for ros::*static-data-vector*,
275+ // meaning that the pointers can be deallocated if
276+ // there are no other references to them.
277+ pointer p=makestring ((char *)name.c_str (), name.size ());
278+ csend (ctx,speval (QSTATICDATAVECTOR)->c .vec .v [index],K_ROSEUS_DELETE,1 ,p);
267279}
268280
269281class EuslispMessage
@@ -410,7 +422,9 @@ class EuslispSubscriptionCallbackHelper : public ros::SubscriptionCallbackHelper
410422 pointer _scb,_args;
411423 EuslispMessage _msg;
412424
413- EuslispSubscriptionCallbackHelper (pointer scb, pointer args,pointer tmpl) : _args(args), _msg(tmpl) {
425+ EuslispSubscriptionCallbackHelper (string name, pointer scb, pointer args, pointer tmpl) :
426+ _args (args), _msg(tmpl)
427+ {
414428 context *ctx = current_ctx;
415429 // ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
416430 // ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
@@ -426,7 +440,7 @@ class EuslispSubscriptionCallbackHelper : public ros::SubscriptionCallbackHelper
426440 ROS_ERROR (" subscription callback function install error" );
427441 }
428442 // avoid gc
429- store_pointer (ctx, cons (ctx,scb,args));
443+ store_pointer (ctx, name, s_mapSubscribedIndex, cons (ctx,scb,args));
430444 }
431445 ~EuslispSubscriptionCallbackHelper () {
432446 ROS_ERROR (" subscription gc" );
@@ -489,7 +503,9 @@ class EuslispServiceCallbackHelper : public ros::ServiceCallbackHelper {
489503 string md5, datatype, requestDataType, responseDataType,
490504 requestMessageDefinition, responseMessageDefinition;
491505
492- EuslispServiceCallbackHelper (pointer scb, pointer args, string smd5, string sdatatype, pointer reqclass, pointer resclass) : _args(args), _req(reqclass), _res(resclass), md5(smd5), datatype(sdatatype) {
506+ EuslispServiceCallbackHelper (string name, pointer scb, pointer args, string smd5, string sdatatype, pointer reqclass, pointer resclass) :
507+ _args (args), _req(reqclass), _res(resclass), md5(smd5), datatype(sdatatype)
508+ {
493509 context *ctx = current_ctx;
494510 // ROS_WARN("func");prinx(ctx,scb,ERROUT);flushstream(ERROUT);terpri(ERROUT);
495511 // ROS_WARN("argc");prinx(ctx,args,ERROUT);flushstream(ERROUT);terpri(ERROUT);
@@ -506,7 +522,7 @@ class EuslispServiceCallbackHelper : public ros::ServiceCallbackHelper {
506522 ROS_ERROR (" service callback function install error" );
507523 }
508524 // avoid gc
509- store_pointer (ctx, cons (ctx,scb,args));
525+ store_pointer (ctx, name, s_mapServicedIndex, cons (ctx,scb,args));
510526
511527 requestDataType = _req.__getDataType ();
512528 responseDataType = _res.__getDataType ();
@@ -667,6 +683,8 @@ pointer ROSEUS(register context *ctx,int n,pointer *argv)
667683 K_ROSEUS_LAST_DURATION = defkeyword (ctx," LAST-DURATION" );
668684 K_ROSEUS_SEC = defkeyword (ctx," SEC" );
669685 K_ROSEUS_NSEC = defkeyword (ctx," NSEC" );
686+ K_ROSEUS_ENTER = defkeyword (ctx," ENTER" );
687+ K_ROSEUS_DELETE = defkeyword (ctx," DELETE" );
670688
671689 s_mapAdvertised.clear ();
672690 s_mapSubscribed.clear ();
@@ -949,7 +967,7 @@ pointer ROSEUS_SUBSCRIBE(register context *ctx,int n,pointer *argv)
949967 EuslispMessage msg (message);
950968 boost::shared_ptr<SubscriptionCallbackHelper> *callback =
951969 (new boost::shared_ptr<SubscriptionCallbackHelper>
952- (new EuslispSubscriptionCallbackHelper (fncallback, args, message)));
970+ (new EuslispSubscriptionCallbackHelper (topicname, fncallback, args, message)));
953971 SubscribeOptions so (topicname, queuesize, msg.__getMD5Sum (), msg.__getDataType ());
954972 so.helper = *callback;
955973 Subscriber subscriber = lnode->subscribe (so);
@@ -972,6 +990,7 @@ pointer ROSEUS_UNSUBSCRIBE(register context *ctx,int n,pointer *argv)
972990 else error (E_NOSTRING);
973991
974992 bool bSuccess = s_mapSubscribed.erase (topicname)>0 ;
993+ erase_pointer (ctx, topicname, s_mapSubscribedIndex);
975994
976995 return (bSuccess?T:NIL);
977996}
@@ -1337,7 +1356,7 @@ pointer ROSEUS_ADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
13371356 pointer response (csend (ctx,emessage,K_ROSEUS_GET,1 ,K_ROSEUS_RESPONSE));
13381357 boost::shared_ptr<EuslispServiceCallbackHelper> *callback =
13391358 (new boost::shared_ptr<EuslispServiceCallbackHelper>
1340- (new EuslispServiceCallbackHelper (fncallback, args, message.__getMD5Sum (),
1359+ (new EuslispServiceCallbackHelper (service, fncallback, args, message.__getMD5Sum (),
13411360 message.__getDataType (), request, response)));
13421361 vpop (); // pop args
13431362
@@ -1369,6 +1388,7 @@ pointer ROSEUS_UNADVERTISE_SERVICE(register context *ctx,int n,pointer *argv)
13691388
13701389 ROS_DEBUG (" unadvertise %s" , service.c_str ());
13711390 bool bSuccess = s_mapServiced.erase (service)>0 ;
1391+ erase_pointer (ctx, service, s_mapServicedIndex);
13721392
13731393 return (bSuccess?T:NIL);
13741394}
@@ -2002,6 +2022,7 @@ class TimerFunction
20022022 // unregister callback when finished
20032023 if (_oneshot) {
20042024 bool bSuccess = s_mapTimered.erase (_funcname)>0 ;
2025+ erase_pointer (ctx, _funcname, s_mapTimeredIndex);
20052026 if (bSuccess) {
20062027 ROS_DEBUG (" one shot timer successfully exited: %s" , _funcname.c_str ());
20072028 }
@@ -2088,7 +2109,7 @@ pointer ROSEUS_CREATE_TIMER(register context *ctx,int n,pointer *argv)
20882109 for (int i=n-1 ;i>=2 ;i--) args=cons (ctx,argv[i],args);
20892110
20902111 // avoid gc
2091- store_pointer (ctx, cons (ctx,fncallback,args));
2112+ store_pointer (ctx, fncallname, s_mapTimeredIndex, cons (ctx,fncallback,args));
20922113
20932114 // ;; store mapTimered
20942115 ROS_DEBUG (" create timer %s at %f (oneshot=%d) (groupname=%s)" , fncallname.c_str (), period, oneshot, groupname.c_str ());
@@ -2124,6 +2145,8 @@ pointer ___roseus(register context *ctx, int n, pointer *argv, pointer env)
21242145 QROSWARN=defvar (ctx," *ROSWARN*" ,makeint (3 ),rospkg);
21252146 QROSERROR=defvar (ctx," *ROSERROR*" ,makeint (4 ),rospkg);
21262147 QROSFATAL=defvar (ctx," *ROSFATAL*" ,makeint (5 ),rospkg);
2148+ QSTATICDATAVECTOR=intern (ctx," *STATIC-DATA-VECTOR*" ,20 ,rospkg);
2149+
21272150 defun (ctx," SPIN" ,argv[0 ],(pointer (*)())ROSEUS_SPIN, " Enter simple event loop" );
21282151
21292152 defun (ctx," SPIN-ONCE" ,argv[0 ],(pointer (*)())ROSEUS_SPINONCE,
0 commit comments